1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "assembler/assembly-emitter.h"
17 #include "assembler/assembly-parser.h"
18 #include "libpandafile/class_data_accessor-inl.h"
19
20 #include "ecmascript/global_env.h"
21 #include "ecmascript/js_function_kind.h"
22 #include "ecmascript/jspandafile/js_pandafile.h"
23 #include "ecmascript/jspandafile/js_pandafile_manager.h"
24 #include "ecmascript/jspandafile/method_literal.h"
25 #include "ecmascript/jspandafile/panda_file_translator.h"
26 #include "ecmascript/jspandafile/program_object.h"
27 #include "ecmascript/tests/test_helper.h"
28
29 using namespace panda::ecmascript;
30 using namespace panda::panda_file;
31 using namespace panda::pandasm;
32
33 namespace panda::test {
34 class PandaFileTranslatorTest : public testing::Test {
35 public:
SetUpTestCase()36 static void SetUpTestCase()
37 {
38 GTEST_LOG_(INFO) << "SetUpTestCase";
39 }
40
TearDownTestCase()41 static void TearDownTestCase()
42 {
43 GTEST_LOG_(INFO) << "TearDownCase";
44 }
45
SetUp()46 void SetUp() override
47 {
48 TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
49 }
50
TearDown()51 void TearDown() override
52 {
53 TestHelper::DestroyEcmaVMWithScope(instance, scope);
54 }
55
56 EcmaVM *instance {nullptr};
57 EcmaHandleScope *scope {nullptr};
58 JSThread *thread {nullptr};
59 };
60
HWTEST_F_L0(PandaFileTranslatorTest,GenerateProgram)61 HWTEST_F_L0(PandaFileTranslatorTest, GenerateProgram)
62 {
63 Parser parser;
64 auto vm = thread->GetEcmaVM();
65 const char *filename = "__PandaFileTranslatorTest1.pa";
66 const uint8_t *typeDesc = utf::CStringAsMutf8("L_GLOBAL;");
67 const char *data = R"(
68 .function any func_main_0(any a0, any a1, any a2) {}
69 .function void func() {}
70 )";
71 auto res = parser.Parse(data);
72 JSPandaFileManager *pfManager = JSPandaFileManager::GetInstance();
73 std::unique_ptr<const File> pfPtr = pandasm::AsmEmitter::Emit(res.Value());
74 std::shared_ptr<JSPandaFile> pf = pfManager->NewJSPandaFile(pfPtr.release(), CString(filename));
75 const File *file = pf->GetPandaFile();
76 File::EntityId classId = file->GetClassId(typeDesc);
77 ClassDataAccessor cda(*file, classId);
78 std::vector<File::EntityId> methodId {};
79 cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
80 methodId.push_back(mda.GetMethodId());
81 });
82 pf->UpdateMainMethodIndex(methodId[0].GetOffset());
83 MethodLiteral *method1 = new MethodLiteral(methodId[0]);
84 MethodLiteral *method2 = new MethodLiteral(methodId[1]);
85 pf->SetMethodLiteralToMap(method1);
86 pf->SetMethodLiteralToMap(method2);
87 pfManager->AddJSPandaFile(pf);
88
89 JSHandle<ecmascript::Program> program1 = pfManager->GenerateProgram(vm, pf.get(), std::string_view("func"));
90 JSHandle<JSFunction> mainFunc1(thread, program1->GetMainFunction(thread));
91 JSHandle<JSTaggedValue> funcName1 = JSFunction::GetFunctionName(thread, JSHandle<JSFunctionBase>(mainFunc1));
92 EXPECT_STREQ(EcmaStringAccessor(JSHandle<EcmaString>::Cast(funcName1)).ToCString(thread).c_str(), "func");
93
94 pf->UpdateMainMethodIndex(methodId[1].GetOffset());
95 JSHandle<ecmascript::Program> program2 = pfManager->GenerateProgram(vm, pf.get(), JSPandaFile::ENTRY_FUNCTION_NAME);
96 JSHandle<JSFunction> mainFunc2(thread, program2->GetMainFunction(thread));
97 JSHandle<JSTaggedValue> funcName2 = JSFunction::GetFunctionName(thread, JSHandle<JSFunctionBase>(mainFunc2));
98 EXPECT_STREQ(EcmaStringAccessor(JSHandle<EcmaString>::Cast(funcName2)).ToCString(thread).c_str(), "func_main_0");
99 }
100
HWTEST_F_L0(PandaFileTranslatorTest,TranslateClasses)101 HWTEST_F_L0(PandaFileTranslatorTest, TranslateClasses)
102 {
103 Parser parser;
104 const char *filename = "__PandaFileTranslatorTest2.pa";
105 const uint8_t *typeDesc = utf::CStringAsMutf8("L_GLOBAL;");
106 const char *data = R"(
107 .function any func_main_0(any a0, any a1, any a2) {
108 ldai 1
109 return
110 }
111 )";
112 auto res = parser.Parse(data);
113 JSPandaFileManager *pfManager = JSPandaFileManager::GetInstance();
114 std::unique_ptr<const File> pfPtr = pandasm::AsmEmitter::Emit(res.Value());
115 std::shared_ptr<JSPandaFile> pf = pfManager->NewJSPandaFile(pfPtr.release(), CString(filename));
116 const File *file = pf->GetPandaFile();
117 File::EntityId classId = file->GetClassId(typeDesc);
118 ClassDataAccessor cda(*file, classId);
119 std::vector<File::EntityId> methodId {};
120 cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
121 methodId.push_back(mda.GetMethodId());
122 });
123 pf->UpdateMainMethodIndex(methodId[0].GetOffset());
124 pfManager->AddJSPandaFile(pf);
125 EXPECT_TRUE(pf->FindMethodLiteral(methodId[0].GetOffset()) == nullptr);
126
127 const char *methodName = MethodLiteral::GetMethodName(pf.get(), methodId[0]);
128 PandaFileTranslator::TranslateClasses(thread, pf.get(), CString(methodName));
129 EXPECT_TRUE(pf->FindMethodLiteral(methodId[0].GetOffset()) != nullptr);
130 EXPECT_EQ(pf->FindMethodLiteral(methodId[0].GetOffset())->GetFunctionKind(),
131 ecmascript::FunctionKind::NONE_FUNCTION);
132 }
133 } // namespace panda::test
134