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/jspandafile/js_pandafile.h"
22 #include "ecmascript/jspandafile/js_pandafile_executor.h"
23 #include "ecmascript/jspandafile/js_pandafile_manager.h"
24 #include "ecmascript/jspandafile/program_object.h"
25 #include "ecmascript/tests/test_helper.h"
26
27 using namespace panda::ecmascript;
28 using namespace panda::panda_file;
29 using namespace panda::pandasm;
30
31 namespace panda::test {
32 class JSPandaFileExecutorTest : public testing::Test {
33 public:
SetUpTestCase()34 static void SetUpTestCase()
35 {
36 GTEST_LOG_(INFO) << "SetUpTestCase";
37 }
38
TearDownTestCase()39 static void TearDownTestCase()
40 {
41 GTEST_LOG_(INFO) << "TearDownCase";
42 }
43
SetUp()44 void SetUp() override
45 {
46 TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
47 }
48
TearDown()49 void TearDown() override
50 {
51 TestHelper::DestroyEcmaVMWithScope(instance, scope);
52 }
53
54 EcmaVM *instance {nullptr};
55 EcmaHandleScope *scope {nullptr};
56 JSThread *thread {nullptr};
57 };
58
HWTEST_F_L0(JSPandaFileExecutorTest,Execute)59 HWTEST_F_L0(JSPandaFileExecutorTest, Execute)
60 {
61 const char *fileName = "__JSPandaFileExecutorTest1.abc";
62 const char *data = R"(
63 .language ECMAScript
64 .function any func_main_0(any a0, any a1, any a2) {
65 ldai 1
66 return
67 }
68 )";
69 JSPandaFileManager *pfManager = JSPandaFileManager::GetInstance();
70 Parser parser;
71 auto res = parser.Parse(data);
72 std::unique_ptr<const File> pfPtr = pandasm::AsmEmitter::Emit(res.Value());
73 std::shared_ptr<JSPandaFile> pf = pfManager->NewJSPandaFile(pfPtr.release(), CString(fileName));
74 const uint8_t *typeDesc = utf::CStringAsMutf8("L_GLOBAL;");
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 *method = new MethodLiteral(methodId[0]);
84 method->Initialize(pf.get());
85 pf->SetMethodLiteralToMap(method);
86 pfManager->AddJSPandaFileVm(instance, pf);
87 Expected<JSTaggedValue, bool> result =
88 JSPandaFileExecutor::Execute(thread, pf.get(), JSPandaFile::ENTRY_MAIN_FUNCTION);
89 EXPECT_TRUE(result);
90
91 pfManager->RemoveJSPandaFileVm(instance, pf.get());
92 }
93
HWTEST_F_L0(JSPandaFileExecutorTest,ExecuteFromFile)94 HWTEST_F_L0(JSPandaFileExecutorTest, ExecuteFromFile)
95 {
96 const char *fileName = "__JSPandaFileExecutorTest2.abc";
97 const char *data = R"(
98 .language ECMAScript
99 .function any func_main_0(any a0, any a1, any a2) {
100 ldai 1
101 return
102 }
103 )";
104 JSPandaFileManager *pfManager = JSPandaFileManager::GetInstance();
105 Parser parser;
106 auto res = parser.Parse(data);
107 std::unique_ptr<const File> pfPtr = pandasm::AsmEmitter::Emit(res.Value());
108 std::shared_ptr<JSPandaFile> pf = pfManager->NewJSPandaFile(pfPtr.release(), CString(fileName));
109 const uint8_t *typeDesc = utf::CStringAsMutf8("L_GLOBAL;");
110 const File *file = pf->GetPandaFile();
111 File::EntityId classId = file->GetClassId(typeDesc);
112 ClassDataAccessor cda(*file, classId);
113 std::vector<File::EntityId> methodId {};
114 cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
115 methodId.push_back(mda.GetMethodId());
116 });
117 pf->UpdateMainMethodIndex(methodId[0].GetOffset());
118 MethodLiteral *method = new MethodLiteral(methodId[0]);
119 method->Initialize(pf.get());
120 pf->SetMethodLiteralToMap(method);
121 pfManager->AddJSPandaFileVm(instance, pf);
122 Expected<JSTaggedValue, bool> result =
123 JSPandaFileExecutor::ExecuteFromAbcFile(thread, CString(fileName), JSPandaFile::ENTRY_MAIN_FUNCTION);
124 EXPECT_TRUE(result);
125
126 pfManager->RemoveJSPandaFileVm(instance, pf.get());
127 std::shared_ptr<JSPandaFile> foundPf = pfManager->FindJSPandaFile(fileName);
128 EXPECT_TRUE(foundPf == nullptr);
129 }
130
HWTEST_F_L0(JSPandaFileExecutorTest,ExecuteFromBuffer)131 HWTEST_F_L0(JSPandaFileExecutorTest, ExecuteFromBuffer)
132 {
133 const char *fileName = "__JSPandaFileExecutorTest3.abc";
134 const char *data = R"(
135 .language ECMAScript
136 .function any func_main_0(any a0, any a1, any a2) {
137 ldai 1
138 return
139 }
140 )";
141 JSPandaFileManager *pfManager = JSPandaFileManager::GetInstance();
142 Parser parser;
143 auto res = parser.Parse(data);
144 std::unique_ptr<const File> pfPtr = pandasm::AsmEmitter::Emit(res.Value());
145 std::shared_ptr<JSPandaFile> pf = pfManager->NewJSPandaFile(pfPtr.release(), CString(fileName));
146 const uint8_t *typeDesc = utf::CStringAsMutf8("L_GLOBAL;");
147 const File *file = pf->GetPandaFile();
148 File::EntityId classId = file->GetClassId(typeDesc);
149 ClassDataAccessor cda(*file, classId);
150 std::vector<File::EntityId> methodId {};
151 cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
152 methodId.push_back(mda.GetMethodId());
153 });
154 pf->UpdateMainMethodIndex(methodId[0].GetOffset());
155 MethodLiteral *method = new MethodLiteral(methodId[0]);
156 method->Initialize(pf.get());
157 pf->SetMethodLiteralToMap(method);
158 pfManager->AddJSPandaFileVm(instance, pf);
159 Expected<JSTaggedValue, bool> result = JSPandaFileExecutor::ExecuteFromBuffer(
160 thread, (void *)data, sizeof(data), JSPandaFile::ENTRY_MAIN_FUNCTION, CString(fileName));
161 EXPECT_TRUE(result);
162
163 pfManager->RemoveJSPandaFileVm(instance, pf.get());
164 std::shared_ptr<JSPandaFile> foundPf = pfManager->FindJSPandaFile(fileName);
165 EXPECT_TRUE(foundPf == nullptr);
166 }
167 } // namespace panda::test
168