• 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     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         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     JSPandaFile *pf = CreateJSPandaFile(source, fileName);
78     EXPECT_TRUE(pf != nullptr);
79     JSPandaFileManager::RemoveJSPandaFile(pf);
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     JSPandaFile *pf = CreateJSPandaFile(source, fileName);
89     const CString expectFileName = pf->GetJSPandaFileDesc();
90     EXPECT_STREQ(expectFileName.c_str(), "test.pa");
91     JSPandaFileManager::RemoveJSPandaFile(pf);
92 }
93 
HWTEST_F_L0(JSPandaFileTest,GetPandaFile)94 HWTEST_F_L0(JSPandaFileTest, GetPandaFile)
95 {
96     const char *source = R"(
97         .function void foo() {}
98     )";
99     const CString fileName = "test.pa";
100     JSPandaFile *pf = CreateJSPandaFile(source, fileName);
101     const File *file = pf->GetPandaFile();
102     EXPECT_TRUE(file != nullptr);
103     JSPandaFileManager::RemoveJSPandaFile(pf);
104 }
105 
HWTEST_F_L0(JSPandaFileTest,GetMethodLiterals_GetNumMethods)106 HWTEST_F_L0(JSPandaFileTest, GetMethodLiterals_GetNumMethods)
107 {
108     const char *source = R"(
109         .function void foo1() {}
110         .function void foo2() {}
111         .function void foo3() {}
112     )";
113     const CString fileName = "test.pa";
114     JSPandaFile *pf = CreateJSPandaFile(source, fileName);
115     MethodLiteral *method = pf->GetMethodLiterals();
116     EXPECT_TRUE(method != nullptr);
117 
118     uint32_t methodNum = pf->GetNumMethods();
119     EXPECT_EQ(methodNum, 3U); // 3 : number of methods
120     JSPandaFileManager::RemoveJSPandaFile(pf);
121 }
122 
HWTEST_F_L0(JSPandaFileTest,SetMethodLiteralToMap_FindMethodLiteral)123 HWTEST_F_L0(JSPandaFileTest, SetMethodLiteralToMap_FindMethodLiteral)
124 {
125     const char *source = R"(
126         .function void foo1() {}
127         .function void foo2() {}
128         .function void foo3() {}
129     )";
130     const CString fileName = "test.pa";
131     JSPandaFile *pf = CreateJSPandaFile(source, fileName);
132     const File *file = pf->GetPandaFile();
133     const uint8_t *typeDesc = utf::CStringAsMutf8("L_GLOBAL;");
134     File::EntityId class_id = file->GetClassId(typeDesc);
135     EXPECT_TRUE(class_id.IsValid());
136 
137     ClassDataAccessor cda(*file, class_id);
138     std::vector<File::EntityId> methodId {};
139     int count = 0;
140     cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
141         methodId.push_back(mda.GetMethodId());
142         count++;
143     });
144     EXPECT_EQ(count, 3); // 3 : number of methods
145 
146     MethodLiteral method1(pf, methodId[0]);
147     MethodLiteral method2(pf, methodId[1]);
148     MethodLiteral method3(pf, methodId[2]);
149     pf->SetMethodLiteralToMap(&method1);
150     pf->SetMethodLiteralToMap(&method2);
151     pf->SetMethodLiteralToMap(&method3);
152     EXPECT_STREQ(MethodLiteral::ParseFunctionName(pf, methodId[0]).c_str(), "foo1");
153     EXPECT_STREQ(MethodLiteral::ParseFunctionName(pf, methodId[1]).c_str(), "foo2");
154     EXPECT_STREQ(MethodLiteral::ParseFunctionName(pf, methodId[2]).c_str(), "foo3");
155     JSPandaFileManager::RemoveJSPandaFile(pf);
156 }
157 
HWTEST_F_L0(JSPandaFileTest,GetOrInsertConstantPool_GetConstpoolIndex_GetConstpoolMap)158 HWTEST_F_L0(JSPandaFileTest, GetOrInsertConstantPool_GetConstpoolIndex_GetConstpoolMap)
159 {
160     const char *source = R"(
161         .function void foo1() {}
162         .function void foo2() {}
163         .function void foo3() {}
164     )";
165     const CString fileName = "test.pa";
166     JSPandaFile *pf = CreateJSPandaFile(source, fileName);
167     const File *file = pf->GetPandaFile();
168     const uint8_t *typeDesc = utf::CStringAsMutf8("L_GLOBAL;");
169     File::EntityId class_id = file->GetClassId(typeDesc);
170     EXPECT_TRUE(class_id.IsValid());
171 
172     ClassDataAccessor cda(*file, class_id);
173     std::vector<File::EntityId> methodId {};
174     int count = 0;
175     cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
176         methodId.push_back(mda.GetMethodId());
177         count++;
178     });
179     EXPECT_EQ(count, 3); // 3 : number of methods
180 
181     uint32_t index1 = pf->GetOrInsertConstantPool(ConstPoolType::METHOD, methodId[0].GetOffset());
182     uint32_t index2 = pf->GetOrInsertConstantPool(ConstPoolType::METHOD, methodId[1].GetOffset());
183     uint32_t index3 = pf->GetOrInsertConstantPool(ConstPoolType::METHOD, methodId[2].GetOffset());
184     EXPECT_EQ(index1, 0U);
185     EXPECT_EQ(index2, 1U);
186     EXPECT_EQ(index3, 2U);
187 
188     uint32_t conPoolIndex = pf->GetConstpoolIndex();
189     EXPECT_EQ(conPoolIndex, 3U);
190 
191     CUnorderedMap<uint32_t, uint64_t> constpoolMap = pf->GetConstpoolMap();
192     ConstPoolValue constPoolValue1(constpoolMap.at(methodId[0].GetOffset()));
193     ConstPoolValue constPoolValue2(constpoolMap.at(methodId[1].GetOffset()));
194     ConstPoolValue constPoolValue3(constpoolMap.at(methodId[2].GetOffset()));
195     ConstPoolType type1 = constPoolValue1.GetConstpoolType();
196     ConstPoolType type2 = constPoolValue2.GetConstpoolType();
197     ConstPoolType type3 = constPoolValue3.GetConstpoolType();
198     uint32_t gotIndex1 = constPoolValue1.GetConstpoolIndex();
199     uint32_t gotIndex2 = constPoolValue2.GetConstpoolIndex();
200     uint32_t gotIndex3 = constPoolValue3.GetConstpoolIndex();
201     EXPECT_EQ(type1, ConstPoolType::METHOD);
202     EXPECT_EQ(type2, ConstPoolType::METHOD);
203     EXPECT_EQ(type3, ConstPoolType::METHOD);
204     EXPECT_EQ(gotIndex1, 0U);
205     EXPECT_EQ(gotIndex2, 1U);
206     EXPECT_EQ(gotIndex3, 2U);
207     JSPandaFileManager::RemoveJSPandaFile(pf);
208 }
209 
HWTEST_F_L0(JSPandaFileTest,GetMainMethodIndex_UpdateMainMethodIndex)210 HWTEST_F_L0(JSPandaFileTest, GetMainMethodIndex_UpdateMainMethodIndex)
211 {
212     const char *source = R"(
213         .function void func1() {}
214         .function void func2() {}
215     )";
216     const CString fileName = "test.pa";
217     JSPandaFile *pf = CreateJSPandaFile(source, fileName);
218     const File *file = pf->GetPandaFile();
219     const uint8_t *typeDesc = utf::CStringAsMutf8("L_GLOBAL;");
220     File::EntityId class_id = file->GetClassId(typeDesc);
221     EXPECT_TRUE(class_id.IsValid());
222 
223     ClassDataAccessor cda(*file, class_id);
224     std::vector<File::EntityId> methodId {};
225     int count = 0;
226     cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
227         methodId.push_back(mda.GetMethodId());
228         count++;
229     });
230     EXPECT_EQ(count, 2); // 2 : number of methods
231 
232     uint32_t mainMethodIndex = pf->GetMainMethodIndex();
233     EXPECT_EQ(mainMethodIndex, 0U);
234 
235     pf->UpdateMainMethodIndex(methodId[0].GetOffset());
236     mainMethodIndex = pf->GetMainMethodIndex();
237     EXPECT_EQ(mainMethodIndex, methodId[0].GetOffset());
238 
239     pf->UpdateMainMethodIndex(methodId[1].GetOffset());
240     mainMethodIndex = pf->GetMainMethodIndex();
241     EXPECT_EQ(mainMethodIndex, methodId[1].GetOffset());
242     JSPandaFileManager::RemoveJSPandaFile(pf);
243 }
244 
HWTEST_F_L0(JSPandaFileTest,GetClasses)245 HWTEST_F_L0(JSPandaFileTest, GetClasses)
246 {
247     const char *source = R"(
248         .function void foo() {}
249     )";
250     const CString fileName = "test.pa";
251     JSPandaFile *pf = CreateJSPandaFile(source, fileName);
252     const File *file = pf->GetPandaFile();
253     const uint8_t *typeDesc = utf::CStringAsMutf8("L_GLOBAL;");
254     File::EntityId class_id = file->GetClassId(typeDesc);
255     EXPECT_TRUE(class_id.IsValid());
256 
257     const File::Header *header = file->GetHeader();
258     Span fileData(file->GetBase(), header->file_size);
259     Span class_idx_data = fileData.SubSpan(header->class_idx_off, header->num_classes * sizeof(uint32_t));
260     auto classesData = Span(reinterpret_cast<const uint32_t *>(class_idx_data.data()), header->num_classes);
261 
262     Span<const uint32_t> classes = pf->GetClasses();
263     EXPECT_EQ(classes.Data(), classesData.Data());
264     JSPandaFileManager::RemoveJSPandaFile(pf);
265 }
266 
HWTEST_F_L0(JSPandaFileTest,IsModule_IsCjs)267 HWTEST_F_L0(JSPandaFileTest, IsModule_IsCjs)
268 {
269     const char *source1 = R"(
270         .function void foo1() {}
271     )";
272     const CString fileName1 = "test1.pa";
273     JSPandaFile *pf1 = CreateJSPandaFile(source1, fileName1);
274     EXPECT_EQ(pf1->IsModule(thread), false);
275     EXPECT_EQ(pf1->IsCjs(thread), false);
276     JSPandaFileManager::RemoveJSPandaFile(pf1);
277 }
278 
HWTEST_F_L0(JSPandaFileTest,SetLoadedAOTStatus_IsLoadedAOT)279 HWTEST_F_L0(JSPandaFileTest, SetLoadedAOTStatus_IsLoadedAOT)
280 {
281     const char *source = R"(
282         .function void foo() {}
283     )";
284     const CString fileName = "test.pa";
285     JSPandaFile *pf = CreateJSPandaFile(source, fileName);
286     bool isLoadedAOT = pf->IsLoadedAOT();
287     EXPECT_EQ(isLoadedAOT, false);
288 
289     pf->SetAOTFileInfoIndex(0);
290     isLoadedAOT = pf->IsLoadedAOT();
291     EXPECT_EQ(isLoadedAOT, true);
292     JSPandaFileManager::RemoveJSPandaFile(pf);
293 }
294 
HWTEST_F_L0(JSPandaFileTest,GetFileUniqId)295 HWTEST_F_L0(JSPandaFileTest, GetFileUniqId)
296 {
297     const char *source = R"(
298         .function void foo() {}
299     )";
300     const CString fileName = "test.pa";
301     JSPandaFile *pf = CreateJSPandaFile(source, fileName);
302     EXPECT_EQ(pf->GetFileUniqId(), merge_hashes(panda_file::File::CalcFilenameHash(""),
303         GetHash32(reinterpret_cast<const uint8_t *>(pf->GetPandaFile()->GetHeader()),
304         sizeof(panda_file::File::Header))));
305     JSPandaFileManager::RemoveJSPandaFile(pf);
306 }
307 
HWTEST_F_L0(JSPandaFileTest,IsParsedConstpoolOfCurrentVM)308 HWTEST_F_L0(JSPandaFileTest, IsParsedConstpoolOfCurrentVM)
309 {
310     const char *source = R"(
311         .function void foo() {}
312     )";
313     const CString fileName = "test.pa";
314     JSPandaFile *pf = CreateJSPandaFile(source, fileName);
315     auto &recordInfo = pf->FindRecordInfo(JSPandaFile::ENTRY_FUNCTION_NAME);
316     EXPECT_TRUE(!recordInfo.IsParsedConstpoolOfCurrentVM(instance));
317     recordInfo.SetParsedConstpoolVM(instance);
318     EXPECT_TRUE(pf->FindRecordInfo(JSPandaFile::ENTRY_FUNCTION_NAME).IsParsedConstpoolOfCurrentVM(instance));
319     JSPandaFileManager::RemoveJSPandaFile(pf);
320 }
321 }  // namespace panda::test