• 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 "gtest/gtest.h"
19 #include "libpandabase/utils/utf.h"
20 #include "libpandafile/class_data_accessor-inl.h"
21 
22 #include "ecmascript/mem/c_containers.h"
23 #include "ecmascript/jspandafile/js_pandafile.h"
24 #include "ecmascript/jspandafile/js_pandafile_manager.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 JSPandaFileTest : 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 protected:
CreateJSPandaFile(const char * source,const CString filename)58     std::shared_ptr<JSPandaFile> CreateJSPandaFile(const char *source, const CString filename)
59     {
60         Parser parser;
61         const std::string fn = "SRC.pa"; // test file name : "SRC.pa"
62         auto res = parser.Parse(source, fn);
63         EXPECT_EQ(parser.ShowError().err, Error::ErrorType::ERR_NONE);
64 
65         std::unique_ptr<const File> pfPtr = pandasm::AsmEmitter::Emit(res.Value());
66         JSPandaFileManager *pfManager = JSPandaFileManager::GetInstance();
67         std::shared_ptr<JSPandaFile> pf = pfManager->NewJSPandaFile(pfPtr.release(), filename);
68         return pf;
69     }
70 };
71 
HWTEST_F_L0(JSPandaFileTest,CreateJSPandaFile)72 HWTEST_F_L0(JSPandaFileTest, CreateJSPandaFile)
73 {
74     const char *source = R"(
75         .function void foo() {}
76     )";
77     const CString fileName = "test.pa";
78     std::shared_ptr<JSPandaFile> pf = CreateJSPandaFile(source, fileName);
79     EXPECT_TRUE(pf != nullptr);
80 }
81 
HWTEST_F_L0(JSPandaFileTest,GetJSPandaFileDesc)82 HWTEST_F_L0(JSPandaFileTest, GetJSPandaFileDesc)
83 {
84     const char *source = R"(
85         .function void foo() {}
86     )";
87     const CString fileName = "test.pa";
88     std::shared_ptr<JSPandaFile> pf = CreateJSPandaFile(source, fileName);
89     const CString expectFileName = pf->GetJSPandaFileDesc();
90     EXPECT_STREQ(expectFileName.c_str(), "test.pa");
91 }
92 
HWTEST_F_L0(JSPandaFileTest,GetPandaFile)93 HWTEST_F_L0(JSPandaFileTest, GetPandaFile)
94 {
95     const char *source = R"(
96         .function void foo() {}
97     )";
98     const CString fileName = "test.pa";
99     std::shared_ptr<JSPandaFile> pf = CreateJSPandaFile(source, fileName);
100     const File *file = pf->GetPandaFile();
101     EXPECT_TRUE(file != nullptr);
102 }
103 
HWTEST_F_L0(JSPandaFileTest,GetMethodLiterals_GetNumMethods)104 HWTEST_F_L0(JSPandaFileTest, GetMethodLiterals_GetNumMethods)
105 {
106     const char *source = R"(
107         .function void foo1() {}
108         .function void foo2() {}
109         .function void foo3() {}
110     )";
111     const CString fileName = "test.pa";
112     std::shared_ptr<JSPandaFile> pf = CreateJSPandaFile(source, fileName);
113     MethodLiteral *method = pf->GetMethodLiterals();
114     EXPECT_TRUE(method != nullptr);
115 
116     uint32_t methodNum = pf->GetNumMethods();
117     EXPECT_EQ(methodNum, 3U); // 3 : number of methods
118 }
119 
HWTEST_F_L0(JSPandaFileTest,SetMethodLiteralToMap_FindMethodLiteral)120 HWTEST_F_L0(JSPandaFileTest, SetMethodLiteralToMap_FindMethodLiteral)
121 {
122     const char *source = R"(
123         .function void foo1() {}
124         .function void foo2() {}
125         .function void foo3() {}
126     )";
127     const CString fileName = "test.pa";
128     std::shared_ptr<JSPandaFile> pf = CreateJSPandaFile(source, fileName);
129     const File *file = pf->GetPandaFile();
130     const uint8_t *typeDesc = utf::CStringAsMutf8("L_GLOBAL;");
131     File::EntityId classId = file->GetClassId(typeDesc);
132     EXPECT_TRUE(classId.IsValid());
133 
134     ClassDataAccessor cda(*file, classId);
135     std::vector<File::EntityId> methodId {};
136     int count = 0;
137     cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
138         methodId.push_back(mda.GetMethodId());
139         count++;
140     });
141     EXPECT_EQ(count, 3); // 3 : number of methods
142 
143     MethodLiteral *method1 = new MethodLiteral(methodId[0]);
144     MethodLiteral *method2 = new MethodLiteral(methodId[1]);
145     MethodLiteral *method3 = new MethodLiteral(methodId[2]);
146     pf->SetMethodLiteralToMap(method1);
147     pf->SetMethodLiteralToMap(method2);
148     pf->SetMethodLiteralToMap(method3);
149     EXPECT_STREQ(MethodLiteral::ParseFunctionName(pf.get(), methodId[0]).c_str(), "foo1");
150     EXPECT_STREQ(MethodLiteral::ParseFunctionName(pf.get(), methodId[1]).c_str(), "foo2");
151     EXPECT_STREQ(MethodLiteral::ParseFunctionName(pf.get(), methodId[2]).c_str(), "foo3");
152 }
153 
HWTEST_F_L0(JSPandaFileTest,GetOrInsertConstantPool_GetConstpoolIndex_GetConstpoolMap)154 HWTEST_F_L0(JSPandaFileTest, GetOrInsertConstantPool_GetConstpoolIndex_GetConstpoolMap)
155 {
156     const char *source = R"(
157         .function void foo1() {}
158         .function void foo2() {}
159         .function void foo3() {}
160     )";
161     const CString fileName = "test.pa";
162     std::shared_ptr<JSPandaFile> pf = CreateJSPandaFile(source, fileName);
163     const File *file = pf->GetPandaFile();
164     const uint8_t *typeDesc = utf::CStringAsMutf8("L_GLOBAL;");
165     File::EntityId classId = file->GetClassId(typeDesc);
166     EXPECT_TRUE(classId.IsValid());
167 
168     ClassDataAccessor cda(*file, classId);
169     std::vector<File::EntityId> methodId {};
170     int count = 0;
171     cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
172         methodId.push_back(mda.GetMethodId());
173         count++;
174     });
175     EXPECT_EQ(count, 3); // 3 : number of methods
176 
177     uint32_t index1 = pf->GetOrInsertConstantPool(ConstPoolType::METHOD, methodId[0].GetOffset());
178     uint32_t index2 = pf->GetOrInsertConstantPool(ConstPoolType::METHOD, methodId[1].GetOffset());
179     uint32_t index3 = pf->GetOrInsertConstantPool(ConstPoolType::METHOD, methodId[2].GetOffset());
180     EXPECT_EQ(index1, 0U);
181     EXPECT_EQ(index2, 1U);
182     EXPECT_EQ(index3, 2U);
183 
184     uint32_t conPoolIndex = pf->GetConstpoolIndex();
185     EXPECT_EQ(conPoolIndex, 3U);
186 
187     CUnorderedMap<uint32_t, uint64_t> constpoolMap = pf->GetConstpoolMap();
188     ConstPoolValue constPoolValue1(constpoolMap.at(methodId[0].GetOffset()));
189     ConstPoolValue constPoolValue2(constpoolMap.at(methodId[1].GetOffset()));
190     ConstPoolValue constPoolValue3(constpoolMap.at(methodId[2].GetOffset()));
191     ConstPoolType type1 = constPoolValue1.GetConstpoolType();
192     ConstPoolType type2 = constPoolValue2.GetConstpoolType();
193     ConstPoolType type3 = constPoolValue3.GetConstpoolType();
194     uint32_t gotIndex1 = constPoolValue1.GetConstpoolIndex();
195     uint32_t gotIndex2 = constPoolValue2.GetConstpoolIndex();
196     uint32_t gotIndex3 = constPoolValue3.GetConstpoolIndex();
197     EXPECT_EQ(type1, ConstPoolType::METHOD);
198     EXPECT_EQ(type2, ConstPoolType::METHOD);
199     EXPECT_EQ(type3, ConstPoolType::METHOD);
200     EXPECT_EQ(gotIndex1, 0U);
201     EXPECT_EQ(gotIndex2, 1U);
202     EXPECT_EQ(gotIndex3, 2U);
203 }
204 
HWTEST_F_L0(JSPandaFileTest,GetMainMethodIndex_UpdateMainMethodIndex)205 HWTEST_F_L0(JSPandaFileTest, GetMainMethodIndex_UpdateMainMethodIndex)
206 {
207     const char *source = R"(
208         .function void func1() {}
209         .function void func2() {}
210     )";
211     const CString fileName = "test.pa";
212     std::shared_ptr<JSPandaFile> pf = CreateJSPandaFile(source, fileName);
213     const File *file = pf->GetPandaFile();
214     const uint8_t *typeDesc = utf::CStringAsMutf8("L_GLOBAL;");
215     File::EntityId classId = file->GetClassId(typeDesc);
216     EXPECT_TRUE(classId.IsValid());
217 
218     ClassDataAccessor cda(*file, classId);
219     std::vector<File::EntityId> methodId {};
220     int count = 0;
221     cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
222         methodId.push_back(mda.GetMethodId());
223         count++;
224     });
225     EXPECT_EQ(count, 2); // 2 : number of methods
226 
227     uint32_t mainMethodIndex = pf->GetMainMethodIndex();
228     EXPECT_EQ(mainMethodIndex, 0U);
229 
230     pf->UpdateMainMethodIndex(methodId[0].GetOffset());
231     mainMethodIndex = pf->GetMainMethodIndex();
232     EXPECT_EQ(mainMethodIndex, methodId[0].GetOffset());
233 
234     pf->UpdateMainMethodIndex(methodId[1].GetOffset());
235     mainMethodIndex = pf->GetMainMethodIndex();
236     EXPECT_EQ(mainMethodIndex, methodId[1].GetOffset());
237 }
238 
HWTEST_F_L0(JSPandaFileTest,GetClasses)239 HWTEST_F_L0(JSPandaFileTest, GetClasses)
240 {
241     const char *source = R"(
242         .function void foo() {}
243     )";
244     const CString fileName = "test.pa";
245     std::shared_ptr<JSPandaFile> pf = CreateJSPandaFile(source, fileName);
246     const File *file = pf->GetPandaFile();
247     const uint8_t *typeDesc = utf::CStringAsMutf8("L_GLOBAL;");
248     File::EntityId classId = file->GetClassId(typeDesc);
249     EXPECT_TRUE(classId.IsValid());
250 
251     const File::Header *header = file->GetHeader();
252     Span fileData(file->GetBase(), header->file_size);
253     Span classIdxData = fileData.SubSpan(header->class_idx_off, header->num_classes * sizeof(uint32_t));
254     auto classesData = Span(reinterpret_cast<const uint32_t *>(classIdxData.data()), header->num_classes);
255 
256     Span<const uint32_t> classes = pf->GetClasses();
257     EXPECT_EQ(classes.Data(), classesData.Data());
258 }
259 
HWTEST_F_L0(JSPandaFileTest,IsModule_IsCjs)260 HWTEST_F_L0(JSPandaFileTest, IsModule_IsCjs)
261 {
262     const char *source1 = R"(
263         .function void foo1() {}
264     )";
265     const CString fileName1 = "test1.pa";
266     std::shared_ptr<JSPandaFile> pf1 = CreateJSPandaFile(source1, fileName1);
267     JSPandaFile::JSRecordInfo info =
268         const_cast<JSPandaFile *>(pf1.get())-> FindRecordInfo(JSPandaFile::ENTRY_FUNCTION_NAME);
269     EXPECT_EQ(pf1->IsModule(&info), false);
270     EXPECT_EQ(pf1->IsCjs(&info), false);
271 }
272 
HWTEST_F_L0(JSPandaFileTest,SetLoadedAOTStatus_IsLoadedAOT)273 HWTEST_F_L0(JSPandaFileTest, SetLoadedAOTStatus_IsLoadedAOT)
274 {
275     const char *source = R"(
276         .function void foo() {}
277     )";
278     const CString fileName = "test.pa";
279     std::shared_ptr<JSPandaFile> pf = CreateJSPandaFile(source, fileName);
280     bool isLoadedAOT = pf->IsLoadedAOT();
281     EXPECT_EQ(isLoadedAOT, false);
282 
283     pf->SetAOTFileInfoIndex(0);
284     isLoadedAOT = pf->IsLoadedAOT();
285     EXPECT_EQ(isLoadedAOT, true);
286 }
287 
HWTEST_F_L0(JSPandaFileTest,GetFileUniqId)288 HWTEST_F_L0(JSPandaFileTest, GetFileUniqId)
289 {
290     const char *source = R"(
291         .function void foo() {}
292     )";
293     const CString fileName = "test.pa";
294     std::shared_ptr<JSPandaFile> pf = CreateJSPandaFile(source, fileName);
295     EXPECT_EQ(pf->GetFileUniqId(), merge_hashes(panda_file::File::CalcFilenameHash(""),
296         GetHash32(reinterpret_cast<const uint8_t *>(pf->GetPandaFile()->GetHeader()),
297         sizeof(panda_file::File::Header))));
298 }
299 
HWTEST_F_L0(JSPandaFileTest,IsParsedConstpoolOfCurrentVM)300 HWTEST_F_L0(JSPandaFileTest, IsParsedConstpoolOfCurrentVM)
301 {
302     const char *source = R"(
303         .function void foo() {}
304     )";
305     const CString fileName = "test.pa";
306     std::shared_ptr<JSPandaFile> pf = CreateJSPandaFile(source, fileName);
307     auto &recordInfo = pf->FindRecordInfo(JSPandaFile::ENTRY_FUNCTION_NAME);
308     EXPECT_TRUE(!recordInfo.IsParsedConstpoolOfCurrentVM(instance));
309     recordInfo.SetParsedConstpoolVM(instance);
310     EXPECT_TRUE(pf->FindRecordInfo(JSPandaFile::ENTRY_FUNCTION_NAME).IsParsedConstpoolOfCurrentVM(instance));
311 }
312 
HWTEST_F_L0(JSPandaFileTest,NormalizedFileDescTest)313 HWTEST_F_L0(JSPandaFileTest, NormalizedFileDescTest)
314 {
315     const char *source = R"(
316         .function void foo() {}
317     )";
318     CString fileName = "/data/storage/el1/bundle/entry/ets/modules.abc";
319     std::shared_ptr<JSPandaFile> pf = CreateJSPandaFile(source, fileName);
320     EXPECT_EQ(pf->GetNormalizedFileDesc(), "entry/ets/modules.abc");
321 
322     fileName = "/data/storage/el1/bundle/entry/ets/widgets.abc";
323     pf = CreateJSPandaFile(source, fileName);
324     EXPECT_EQ(pf->GetNormalizedFileDesc(), "entry/ets/widgets.abc");
325 
326     fileName = "/data/app/el1/bundle/public/com.xx.xx/entry.hsp/entry/ets/modules.abc";
327     pf = CreateJSPandaFile(source, fileName);
328     EXPECT_EQ(pf->GetNormalizedFileDesc(), "entry/ets/modules.abc");
329 
330     fileName = "/data/app/el1/bundle/public/com.xx.xx/entry.hap/entry/ets/widgets.abc";
331     pf = CreateJSPandaFile(source, fileName);
332     EXPECT_EQ(pf->GetNormalizedFileDesc(), "entry/ets/widgets.abc");
333 
334     fileName = "/system/app/Camera/Camera.hap/entry1/ets/modules.abc";
335     pf = CreateJSPandaFile(source, fileName);
336     EXPECT_EQ(pf->GetNormalizedFileDesc(), "entry1/ets/modules.abc");
337 
338     fileName = "test.pa";
339     pf = CreateJSPandaFile(source, fileName);
340     EXPECT_EQ(pf->GetNormalizedFileDesc(), fileName);
341 
342     fileName = "libapp.ability.AbilityStage.z.so/app.ability.AbilityStage.js";
343     pf = CreateJSPandaFile(source, fileName);
344     EXPECT_EQ(pf->GetNormalizedFileDesc(), fileName);
345 }
346 }  // namespace panda::test