• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "libziparchive/zip_archive.h"
20 
21 #include "ecmascript/global_env.h"
22 #include "ecmascript/jspandafile/js_pandafile.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 JSPandaFileManagerTest : 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(JSPandaFileManagerTest,GetInstance)59 HWTEST_F_L0(JSPandaFileManagerTest, GetInstance)
60 {
61     JSPandaFileManager *manager = JSPandaFileManager::GetInstance();
62     EXPECT_TRUE(manager != nullptr);
63 }
64 
HWTEST_F_L0(JSPandaFileManagerTest,NewJSPandaFile)65 HWTEST_F_L0(JSPandaFileManagerTest, NewJSPandaFile)
66 {
67     Parser parser;
68     std::string fileName = "__JSPandaFileManagerTest.pa";
69     const char *source = R"(
70         .function void foo() {}
71     )";
72     auto res = parser.Parse(source, fileName);
73     EXPECT_EQ(parser.ShowError().err, Error::ErrorType::ERR_NONE);
74 
75     std::unique_ptr<const File> pfPtr = pandasm::AsmEmitter::Emit(res.Value());
76     JSPandaFileManager *pfManager = JSPandaFileManager::GetInstance();
77     JSPandaFile *pf = pfManager->NewJSPandaFile(pfPtr.release(), CString(fileName.c_str()));
78     EXPECT_TRUE(pf != nullptr);
79 
80     auto expectFileName = pf->GetJSPandaFileDesc();
81     EXPECT_STREQ(expectFileName.c_str(), "__JSPandaFileManagerTest.pa");
82     remove(fileName.c_str());
83     JSPandaFileManager::RemoveJSPandaFile(pf);
84 }
85 
HWTEST_F_L0(JSPandaFileManagerTest,OpenJSPandaFile)86 HWTEST_F_L0(JSPandaFileManagerTest, OpenJSPandaFile)
87 {
88     const char *filename = "__JSPandaFileManagerTest.pa";
89     const char *data = R"(
90         .function void foo() {}
91     )";
92     JSPandaFileManager *pfManager = JSPandaFileManager::GetInstance();
93     JSPandaFile *ojspf = pfManager->OpenJSPandaFile(filename);
94     EXPECT_TRUE(ojspf == nullptr);
95 
96     Parser parser;
97     auto res = parser.Parse(data);
98     EXPECT_TRUE(pandasm::AsmEmitter::Emit(filename, res.Value()));
99 
100     ojspf = pfManager->OpenJSPandaFile(filename);
101     EXPECT_TRUE(ojspf != nullptr);
102     EXPECT_STREQ(ojspf->GetJSPandaFileDesc().c_str(), "__JSPandaFileManagerTest.pa");
103     JSPandaFileManager::RemoveJSPandaFile(ojspf);
104 
105     remove(filename);
106     ojspf = pfManager->OpenJSPandaFile(filename);
107     EXPECT_TRUE(ojspf == nullptr);
108 }
109 
HWTEST_F_L0(JSPandaFileManagerTest,Insert_Find_Remove_JSPandaFile)110 HWTEST_F_L0(JSPandaFileManagerTest, Insert_Find_Remove_JSPandaFile)
111 {
112     const char *filename1 = "__JSPandaFileManagerTest1.pa";
113     const char *filename2 = "__JSPandaFileManagerTest2.pa";
114     const char *data = R"(
115         .function void foo() {}
116     )";
117     JSPandaFileManager *pfManager = JSPandaFileManager::GetInstance();
118     Parser parser;
119     auto res = parser.Parse(data);
120     std::unique_ptr<const File> pfPtr1 = pandasm::AsmEmitter::Emit(res.Value());
121     std::unique_ptr<const File> pfPtr2 = pandasm::AsmEmitter::Emit(res.Value());
122     JSPandaFile *pf1 = pfManager->NewJSPandaFile(pfPtr1.release(), CString(filename1));
123     JSPandaFile *pf2 = pfManager->NewJSPandaFile(pfPtr2.release(), CString(filename2));
124     pfManager->InsertJSPandaFile(pf1);
125     pfManager->InsertJSPandaFile(pf2);
126     const JSPandaFile *foundPf1 = pfManager->FindJSPandaFile(filename1);
127     const JSPandaFile *foundPf2 = pfManager->FindJSPandaFile(filename2);
128     EXPECT_STREQ(foundPf1->GetJSPandaFileDesc().c_str(), "__JSPandaFileManagerTest1.pa");
129     EXPECT_STREQ(foundPf2->GetJSPandaFileDesc().c_str(), "__JSPandaFileManagerTest2.pa");
130 
131     pfManager->RemoveJSPandaFile((void *)pf1);
132     pfManager->RemoveJSPandaFile((void *)pf2);
133     const JSPandaFile *afterRemovePf1 = pfManager->FindJSPandaFile(filename1);
134     const JSPandaFile *afterRemovePf2 = pfManager->FindJSPandaFile(filename2);
135     EXPECT_EQ(afterRemovePf1, nullptr);
136     EXPECT_EQ(afterRemovePf2, nullptr);
137 }
138 
HWTEST_F_L0(JSPandaFileManagerTest,LoadJSPandaFile)139 HWTEST_F_L0(JSPandaFileManagerTest, LoadJSPandaFile)
140 {
141     const char *filename1 = "__JSPandaFileManagerTest1.pa";
142     const char *filename2 = "__JSPandaFileManagerTest2.pa";
143     const char *data = R"(
144         .function void foo() {}
145     )";
146     JSPandaFileManager *pfManager = JSPandaFileManager::GetInstance();
147     Parser parser;
148     auto res = parser.Parse(data);
149     std::unique_ptr<const File> pfPtr1 = pandasm::AsmEmitter::Emit(res.Value());
150     std::unique_ptr<const File> pfPtr2 = pandasm::AsmEmitter::Emit(res.Value());
151     JSPandaFile *pf1 = pfManager->NewJSPandaFile(pfPtr1.release(), CString(filename1));
152     JSPandaFile *pf2 = pfManager->NewJSPandaFile(pfPtr2.release(), CString(filename2));
153     pfManager->InsertJSPandaFile(pf1);
154     pfManager->InsertJSPandaFile(pf2);
155     const JSPandaFile *loadedPf1 = pfManager->LoadJSPandaFile(thread, filename1, JSPandaFile::ENTRY_MAIN_FUNCTION);
156     const JSPandaFile *loadedPf2 =
157         pfManager->LoadJSPandaFile(thread, filename2, JSPandaFile::ENTRY_MAIN_FUNCTION, (void *)data, sizeof(data));
158     EXPECT_TRUE(loadedPf1 != nullptr);
159     EXPECT_TRUE(loadedPf2 != nullptr);
160     EXPECT_STREQ(loadedPf1->GetJSPandaFileDesc().c_str(), "__JSPandaFileManagerTest1.pa");
161     EXPECT_STREQ(loadedPf2->GetJSPandaFileDesc().c_str(), "__JSPandaFileManagerTest2.pa");
162 
163     pfManager->RemoveJSPandaFile((void *)pf1);
164     pfManager->RemoveJSPandaFile((void *)pf2);
165     pfManager->RemoveJSPandaFile((void *)loadedPf1);
166     pfManager->RemoveJSPandaFile((void *)loadedPf2);
167 }
168 
HWTEST_F_L0(JSPandaFileManagerTest,GenerateProgram)169 HWTEST_F_L0(JSPandaFileManagerTest, GenerateProgram)
170 {
171     Parser parser;
172     auto vm = thread->GetEcmaVM();
173     const char *filename = "__JSPandaFileManagerTest.pa";
174     const uint8_t *typeDesc = utf::CStringAsMutf8("L_GLOBAL;");
175     const char *data = R"(
176         .function void foo() {}
177     )";
178     auto res = parser.Parse(data);
179     JSPandaFileManager *pfManager = JSPandaFileManager::GetInstance();
180     std::unique_ptr<const File> pfPtr = pandasm::AsmEmitter::Emit(res.Value());
181     JSPandaFile *pf = pfManager->NewJSPandaFile(pfPtr.release(), CString(filename));
182     const File *file = pf->GetPandaFile();
183     File::EntityId class_id = file->GetClassId(typeDesc);
184     ClassDataAccessor cda(*file, class_id);
185     std::vector<File::EntityId> methodId {};
186     cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
187         methodId.push_back(mda.GetMethodId());
188     });
189     pf->UpdateMainMethodIndex(methodId[0].GetOffset());
190     MethodLiteral method(pf, methodId[0]);
191     pf->SetMethodLiteralToMap(&method);
192     pfManager->InsertJSPandaFile(pf);
193 
194     JSHandle<ecmascript::Program> program = pfManager->GenerateProgram(vm, pf, JSPandaFile::ENTRY_FUNCTION_NAME);
195     JSHandle<JSFunction> mainFunc(thread, program->GetMainFunction());
196     JSHandle<JSTaggedValue> funcName = JSFunction::GetFunctionName(thread, JSHandle<JSFunctionBase>(mainFunc));
197     EXPECT_STREQ(EcmaStringAccessor(JSHandle<EcmaString>::Cast(funcName)).ToCString().c_str(), "foo");
198 
199     pfManager->RemoveJSPandaFile((void *)pf);
200 }
201 
HWTEST_F_L0(JSPandaFileManagerTest,GetJSPtExtractor)202 HWTEST_F_L0(JSPandaFileManagerTest, GetJSPtExtractor)
203 {
204     const char *filename = "__JSPandaFileManagerTest.pa";
205     const char *data = R"(
206         .function void foo() {}
207     )";
208     Parser parser;
209     auto res = parser.Parse(data);
210     JSPandaFileManager *pfManager = JSPandaFileManager::GetInstance();
211     std::unique_ptr<const File> pfPtr = pandasm::AsmEmitter::Emit(res.Value());
212     JSPandaFile *pf = pfManager->NewJSPandaFile(pfPtr.release(), CString(filename));
213     pfManager->InsertJSPandaFile(pf);
214     DebugInfoExtractor *extractor = pfManager->GetJSPtExtractor(pf);
215     EXPECT_TRUE(extractor != nullptr);
216 
217     pfManager->RemoveJSPandaFile((void *)pf);
218 }
219 
HWTEST_F_L0(JSPandaFileManagerTest,EnumerateJSPandaFiles)220 HWTEST_F_L0(JSPandaFileManagerTest, EnumerateJSPandaFiles)
221 {
222     const char *filename1 = "__JSPandaFileManagerTest3.pa";
223     const char *filename2 = "__JSPandaFileManagerTest4.pa";
224     const char *data = R"(
225         .function void foo() {}
226     )";
227     Parser parser;
228     auto res = parser.Parse(data);
229     JSPandaFileManager *pfManager = JSPandaFileManager::GetInstance();
230     std::unique_ptr<const File> pfPtr1 = pandasm::AsmEmitter::Emit(res.Value());
231     std::unique_ptr<const File> pfPtr2 = pandasm::AsmEmitter::Emit(res.Value());
232     JSPandaFile *pf1 = pfManager->NewJSPandaFile(pfPtr1.release(), CString(filename1));
233     JSPandaFile *pf2 = pfManager->NewJSPandaFile(pfPtr2.release(), CString(filename2));
234     pfManager->InsertJSPandaFile(pf1);
235     pfManager->InsertJSPandaFile(pf2);
236     std::vector<CString> descList{};
237     int count = 0;
238     pfManager->EnumerateJSPandaFiles([&](const JSPandaFile *file) -> bool {
239         auto desc = file->GetJSPandaFileDesc();
240         descList.push_back(desc);
241         count++;
242         return true;
243     });
244     EXPECT_EQ(count, 2); // 2 : test number of files
245     // Sort by the hash value of the element, the output is unordered
246     EXPECT_STREQ(descList[0].c_str(), "__JSPandaFileManagerTest4.pa");
247     EXPECT_STREQ(descList[1].c_str(), "__JSPandaFileManagerTest3.pa");
248 
249     pfManager->RemoveJSPandaFile((void *)pf1);
250     pfManager->RemoveJSPandaFile((void *)pf2);
251 }
252 }  // namespace panda::test
253