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