• 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 <cstdint>
17 #include <fstream>
18 #include <memory>
19 #include <sstream>
20 #include <string>
21 #include "ecmascript/object_factory.h"
22 #include "gtest/gtest.h"
23 
24 #include "assembler/assembly-emitter.h"
25 #include "assembler/assembly-parser.h"
26 #include "ecmascript/ecma_vm.h"
27 #include "ecmascript/js_thread.h"
28 #include "ecmascript/jspandafile/js_pandafile.h"
29 #include "ecmascript/jspandafile/js_pandafile_manager.h"
30 #include "ecmascript/jspandafile/method_literal.h"
31 #include "ecmascript/napi/include/jsnapi.h"
32 #include "ecmascript/pgo_profiler/pgo_profiler_decoder.h"
33 #include "ecmascript/pgo_profiler/pgo_profiler_info.h"
34 #include "ecmascript/pgo_profiler/pgo_profiler_manager.h"
35 #include "ecmascript/tests/test_helper.h"
36 #include "ecmascript/jspandafile/program_object.h"
37 
38 using namespace panda;
39 using namespace panda::ecmascript;
40 using namespace panda::panda_file;
41 using namespace panda::pandasm;
42 
43 namespace panda::test {
44 class PGOProfilerTest : public testing::Test {
45 public:
46     using ApGenMode = PGOProfilerEncoder::ApGenMode;
SetUpTestCase()47     static void SetUpTestCase()
48     {
49         GTEST_LOG_(INFO) << "SetUpTestCase";
50     }
51 
TearDownTestCase()52     static void TearDownTestCase()
53     {
54         GTEST_LOG_(INFO) << "TearDownCase";
55     }
56 
TearDown()57     void TearDown() override
58     {
59         vm_ = nullptr;
60         PGOProfilerManager::GetInstance()->Destroy();
61     }
62 
63 protected:
CreateJSPandaFile(const char * source,const CString filename,std::vector<MethodLiteral * > & methodLiterals)64     std::shared_ptr<JSPandaFile> CreateJSPandaFile(const char *source, const CString filename,
65                                                    std::vector<MethodLiteral *> &methodLiterals)
66     {
67         Parser parser;
68         const std::string fn = "SRC.abc";  // test file name : "SRC.abc"
69         auto res = parser.Parse(source, fn);
70 
71         std::unique_ptr<const File> pfPtr = pandasm::AsmEmitter::Emit(res.Value());
72         JSPandaFileManager *pfManager = JSPandaFileManager::GetInstance();
73         std::shared_ptr<JSPandaFile> pf = pfManager->NewJSPandaFile(pfPtr.release(), filename);
74 
75         const File *file = pf->GetPandaFile();
76         const uint8_t *typeDesc = utf::CStringAsMutf8("L_GLOBAL;");
77         File::EntityId classId = file->GetClassId(typeDesc);
78         EXPECT_TRUE(classId.IsValid());
79 
80         ClassDataAccessor cda(*file, classId);
81         cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
82             auto *methodLiteral = new MethodLiteral(mda.GetMethodId());
83             methodLiteral->Initialize(pf.get());
84             pf->SetMethodLiteralToMap(methodLiteral);
85             methodLiterals.push_back(methodLiteral);
86         });
87         return pf;
88     }
89 
ExecuteAndLoadJSPandaFile(std::string profDir,std::string recordName)90     std::shared_ptr<JSPandaFile> ExecuteAndLoadJSPandaFile(std::string profDir, std::string recordName)
91     {
92         RuntimeOption option;
93         option.SetLogLevel(LOG_LEVEL::INFO);
94         option.SetEnableProfile(true);
95         option.SetProfileDir(profDir);
96         vm_ = JSNApi::CreateJSVM(option);
97         JSNApi::EnableUserUncaughtErrorHandler(vm_);
98 
99         std::string targetAbcPath = TARGET_ABC_PATH + recordName + ".abc";
100         auto result = JSNApi::Execute(vm_, targetAbcPath, recordName, false);
101         EXPECT_TRUE(result);
102 
103         std::shared_ptr<JSPandaFile> jsPandaFile =
104             JSPandaFileManager::GetInstance()->FindJSPandaFile(CString(targetAbcPath));
105 
106         JSNApi::DestroyJSVM(vm_);
107         return jsPandaFile;
108     }
109 
110     EcmaVM *vm_ = nullptr;
111 };
112 
HWTEST_F_L0(PGOProfilerTest,Sample)113 HWTEST_F_L0(PGOProfilerTest, Sample)
114 {
115     const char *source = R"(
116         .language ECMAScript
117         .function void foo1(any a0, any a1, any a2) {}
118     )";
119     std::vector<MethodLiteral *> methodLiterals {};
120     std::shared_ptr<JSPandaFile> pf = CreateJSPandaFile(source, "ark-profiler.abc", methodLiterals);
121     EXPECT_EQ(methodLiterals.size(), 1);  // number of methods
122 
123     mkdir("ark-profiler/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
124     RuntimeOption option;
125     option.SetEnableProfile(true);
126     option.SetProfileDir("ark-profiler/");
127     vm_ = JSNApi::CreateJSVM(option);
128     JSHandle<ConstantPool> constPool = vm_->GetFactory()->NewConstantPool(4);
129     constPool->SetJSPandaFile(pf.get());
130     uint32_t checksum = 304293;
131     PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum);
132     ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
133 
134     JSHandle<Method> method = vm_->GetFactory()->NewMethod(methodLiterals[0]);
135     method->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
136     JSHandle<JSFunction> func = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method);
137     JSHandle<JSTaggedValue> recordName(vm_->GetFactory()->NewFromStdString("test"));
138     func->SetModule(vm_->GetJSThread(), recordName);
139     vm_->GetPGOProfiler()->SetSaveTimestamp(std::chrono::system_clock::now());
140     vm_->GetPGOProfiler()->ProfileCall(JSTaggedValue::VALUE_UNDEFINED, func.GetTaggedType());
141     JSNApi::DestroyJSVM(vm_);
142     // Loader
143     PGOProfilerDecoder loader("ark-profiler/modules.ap", 2);
144     CString expectRecordName = "test";
145 #if defined(SUPPORT_ENABLE_ASM_INTERP)
146     ASSERT_TRUE(loader.LoadAndVerify(checksum));
147     ASSERT_TRUE(!loader.Match(expectRecordName, methodLiterals[0]->GetMethodId()));
148 #else
149     ASSERT_TRUE(!loader.LoadAndVerify(checksum));
150     ASSERT_TRUE(loader.Match(expectRecordName, methodLiterals[0]->GetMethodId()));
151 #endif
152     unlink("ark-profiler/modules.ap");
153     rmdir("ark-profiler/");
154 }
155 
HWTEST_F_L0(PGOProfilerTest,Sample1)156 HWTEST_F_L0(PGOProfilerTest, Sample1)
157 {
158     const char *source = R"(
159         .language ECMAScript
160         .function void foo1(any a0, any a1, any a2) {
161             lda.str "helloworld"
162             return
163         }
164         .function void foo2(any a0, any a1, any a2) {}
165         .function void foo3(any a0, any a1, any a2) {}
166     )";
167     std::vector<MethodLiteral *> methodLiterals {};
168     std::shared_ptr<JSPandaFile> pf = CreateJSPandaFile(source, "ark-profiler1.abc", methodLiterals);
169     EXPECT_EQ(methodLiterals.size(), 3);  // number of methods
170 
171     mkdir("ark-profiler1/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
172     RuntimeOption option;
173     option.SetEnableProfile(true);
174     option.SetProfileDir("ark-profiler1/");
175     vm_ = JSNApi::CreateJSVM(option);
176     JSHandle<ConstantPool> constPool = vm_->GetFactory()->NewConstantPool(4);
177     constPool->SetJSPandaFile(pf.get());
178     uint32_t checksum = 304293;
179     PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum);
180     ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
181 
182     JSHandle<Method> method = vm_->GetFactory()->NewMethod(methodLiterals[0]);
183     JSHandle<Method> method1 = vm_->GetFactory()->NewMethod(methodLiterals[1]);
184     JSHandle<Method> method2 = vm_->GetFactory()->NewMethod(methodLiterals[2]);
185     method->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
186     method1->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
187     method2->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
188 
189     JSHandle<JSFunction> func = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method);
190     JSHandle<JSFunction> func1 = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method1);
191     JSHandle<JSFunction> func2 = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method2);
192     JSHandle<JSTaggedValue> recordName(vm_->GetFactory()->NewFromStdString("test"));
193     func->SetModule(vm_->GetJSThread(), recordName);
194     func1->SetModule(vm_->GetJSThread(), recordName);
195     func2->SetModule(vm_->GetJSThread(), recordName);
196     for (int i = 0; i < 5; i++) {
197         vm_->GetPGOProfiler()->ProfileCall(JSTaggedValue::VALUE_UNDEFINED, func.GetTaggedType());
198     }
199     for (int i = 0; i < 50; i++) {
200         vm_->GetPGOProfiler()->ProfileCall(JSTaggedValue::VALUE_UNDEFINED, func2.GetTaggedType());
201     }
202     vm_->GetPGOProfiler()->ProfileCall(JSTaggedValue::VALUE_UNDEFINED, func1.GetTaggedType());
203     JSNApi::DestroyJSVM(vm_);
204 
205     // Loader
206     PGOProfilerDecoder loader("ark-profiler1/modules.ap", 2);
207     CString expectRecordName = "test";
208 #if defined(SUPPORT_ENABLE_ASM_INTERP)
209     ASSERT_TRUE(loader.LoadAndVerify(checksum));
210     for (uint32_t idx = 0; idx < 3; idx++) {
211         loader.MatchAndMarkMethod(expectRecordName,
212                                  methodLiterals[idx]->GetMethodName(pf.get(), methodLiterals[idx]->GetMethodId()),
213                                  methodLiterals[idx]->GetMethodId());
214     }
215     ASSERT_TRUE(loader.Match(expectRecordName, methodLiterals[0]->GetMethodId()));
216     ASSERT_TRUE(loader.Match(expectRecordName, methodLiterals[2]->GetMethodId()));
217     ASSERT_TRUE(!loader.Match(expectRecordName, methodLiterals[1]->GetMethodId()));
218 #else
219     ASSERT_TRUE(!loader.LoadAndVerify(checksum));
220     ASSERT_TRUE(loader.Match(expectRecordName, methodLiterals[1]->GetMethodId()));
221 #endif
222     unlink("ark-profiler1/modules.ap");
223     rmdir("ark-profiler1/");
224 }
225 
HWTEST_F_L0(PGOProfilerTest,Sample2)226 HWTEST_F_L0(PGOProfilerTest, Sample2)
227 {
228     const char *source = R"(
229         .language ECMAScript
230         .function void foo1(any a0, any a1, any a2) {}
231         .function void foo2(any a0, any a1, any a2) {}
232     )";
233     std::vector<MethodLiteral *> methodLiterals {};
234     std::shared_ptr<JSPandaFile> pf = CreateJSPandaFile(source, "ark-profiler2.abc", methodLiterals);
235     EXPECT_EQ(methodLiterals.size(), 2);  // number of methods
236 
237     mkdir("ark-profiler2/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
238     RuntimeOption option;
239     option.SetEnableProfile(true);
240     option.SetProfileDir("ark-profiler2/");
241     vm_ = JSNApi::CreateJSVM(option);
242     JSHandle<ConstantPool> constPool = vm_->GetFactory()->NewConstantPool(4);
243     constPool->SetJSPandaFile(pf.get());
244     ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
245     uint32_t checksum = 304293;
246     PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum);
247 
248     JSHandle<Method> method = vm_->GetFactory()->NewMethod(methodLiterals[0]);
249     JSHandle<Method> method1 = vm_->GetFactory()->NewMethod(methodLiterals[1]);
250 
251     method->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
252     method1->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
253     JSHandle<JSFunction> func = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method);
254     JSHandle<JSTaggedValue> recordName(vm_->GetFactory()->NewFromStdString("test"));
255     func->SetModule(vm_->GetJSThread(), recordName);
256     JSHandle<JSFunction> func1 = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method1);
257     JSHandle<JSTaggedValue> recordName1(vm_->GetFactory()->NewFromStdString("test1"));
258     func1->SetModule(vm_->GetJSThread(), recordName1);
259     vm_->GetPGOProfiler()->ProfileCall(JSTaggedValue::VALUE_UNDEFINED, func.GetTaggedType());
260     for (int i = 0; i < 5; i++) {
261         vm_->GetPGOProfiler()->ProfileCall(JSTaggedValue::VALUE_UNDEFINED, func1.GetTaggedType());
262     }
263     JSNApi::DestroyJSVM(vm_);
264 
265     // Loader
266     PGOProfilerDecoder loader("ark-profiler2/modules.ap", 2);
267     CString expectRecordName = "test";
268     CString expectRecordName1 = "test1";
269 #if defined(SUPPORT_ENABLE_ASM_INTERP)
270     ASSERT_TRUE(loader.LoadAndVerify(checksum));
271     for (uint32_t idx = 0; idx < 2; idx++) {
272         loader.MatchAndMarkMethod(expectRecordName,
273                                  methodLiterals[idx]->GetMethodName(pf.get(), methodLiterals[idx]->GetMethodId()),
274                                  methodLiterals[idx]->GetMethodId());
275         loader.MatchAndMarkMethod(expectRecordName1,
276                                  methodLiterals[idx]->GetMethodName(pf.get(), methodLiterals[idx]->GetMethodId()),
277                                  methodLiterals[idx]->GetMethodId());
278     }
279     ASSERT_TRUE(!loader.Match(expectRecordName, methodLiterals[0]->GetMethodId()));
280 #else
281     ASSERT_TRUE(!loader.LoadAndVerify(checksum));
282     ASSERT_TRUE(loader.Match(expectRecordName, methodLiterals[0]->GetMethodId()));
283 #endif
284     ASSERT_TRUE(loader.Match(expectRecordName1, methodLiterals[1]->GetMethodId()));
285     unlink("ark-profiler2/modules.ap");
286     rmdir("ark-profiler2/");
287 }
288 
HWTEST_F_L0(PGOProfilerTest,DisEnableSample)289 HWTEST_F_L0(PGOProfilerTest, DisEnableSample)
290 {
291     const char *source = R"(
292         .language ECMAScript
293         .function void foo1(any a0, any a1, any a2) {}
294     )";
295     std::vector<MethodLiteral *> methodLiterals {};
296     std::shared_ptr<JSPandaFile> pf = CreateJSPandaFile(source, "ark-profiler3.abc", methodLiterals);
297     EXPECT_EQ(methodLiterals.size(), 1);  // number of methods
298     mkdir("ark-profiler3/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
299     RuntimeOption option;
300     option.SetEnableProfile(false);
301     option.SetProfileDir("ark-profiler3/");
302     vm_ = JSNApi::CreateJSVM(option);
303     JSHandle<ConstantPool> constPool = vm_->GetFactory()->NewConstantPool(4);
304     constPool->SetJSPandaFile(pf.get());
305     uint32_t checksum = 304293;
306     PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum);
307     ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
308 
309     JSHandle<Method> method = vm_->GetFactory()->NewMethod(methodLiterals[0]);
310 
311     method->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
312     JSHandle<JSFunction> func = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method);
313     JSHandle<JSTaggedValue> recordName(vm_->GetFactory()->NewFromStdString("test"));
314     func->SetModule(vm_->GetJSThread(), recordName);
315     vm_->GetPGOProfiler()->ProfileCall(JSTaggedValue::VALUE_UNDEFINED, func.GetTaggedType());
316     JSNApi::DestroyJSVM(vm_);
317 
318     // Loader
319     PGOProfilerDecoder loader("ark-profiler3/modules.ap", 2);
320     // path is empty()
321     ASSERT_TRUE(!loader.LoadAndVerify(checksum));
322     CString expectRecordName = "test";
323     ASSERT_TRUE(loader.Match(expectRecordName, methodLiterals[0]->GetMethodId()));
324     rmdir("ark-profiler3/");
325 }
326 
HWTEST_F_L0(PGOProfilerTest,PGOProfilerManagerInvalidPath)327 HWTEST_F_L0(PGOProfilerTest, PGOProfilerManagerInvalidPath)
328 {
329     RuntimeOption option;
330     option.SetEnableProfile(true);
331     option.SetProfileDir("ark-profiler4");
332     vm_ = JSNApi::CreateJSVM(option);
333     ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
334     JSNApi::DestroyJSVM(vm_);
335 }
336 
HWTEST_F_L0(PGOProfilerTest,PGOProfilerManagerInitialize)337 HWTEST_F_L0(PGOProfilerTest, PGOProfilerManagerInitialize)
338 {
339     RuntimeOption option;
340     option.SetEnableProfile(true);
341     // outDir is empty
342     option.SetProfileDir("");
343     vm_ = JSNApi::CreateJSVM(option);
344     ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
345 
346     JSNApi::DestroyJSVM(vm_);
347 }
348 
HWTEST_F_L0(PGOProfilerTest,PGOProfilerManagerSample)349 HWTEST_F_L0(PGOProfilerTest, PGOProfilerManagerSample)
350 {
351     RuntimeOption option;
352     option.SetEnableProfile(true);
353     char currentPath[PATH_MAX + 2];
354     if (memset_s(currentPath, PATH_MAX, 1, PATH_MAX) != EOK) {
355         ASSERT_TRUE(false);
356     }
357     currentPath[PATH_MAX + 1] = '\0';
358     option.SetProfileDir(currentPath);
359     vm_ = JSNApi::CreateJSVM(option);
360     uint32_t checksum = 304293;
361     PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum);
362     ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
363 
364     JSHandle<JSArray> array = vm_->GetFactory()->NewJSArray();
365     vm_->GetPGOProfiler()->ProfileCall(JSTaggedValue::VALUE_UNDEFINED, array.GetTaggedType());
366 
367     // RecordName is hole
368     MethodLiteral *methodLiteral = new MethodLiteral(EntityId(61));
369     JSHandle<Method> method = vm_->GetFactory()->NewMethod(methodLiteral);
370     JSHandle<JSFunction> func = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method);
371     func->SetModule(vm_->GetJSThread(), JSTaggedValue::Hole());
372     vm_->GetPGOProfiler()->ProfileCall(JSTaggedValue::VALUE_UNDEFINED, func.GetTaggedType());
373     JSNApi::DestroyJSVM(vm_);
374 
375     PGOProfilerDecoder loader("", 2);
376     // path is empty()
377     ASSERT_TRUE(loader.LoadAndVerify(checksum));
378     // path size greater than PATH_MAX
379     char path[PATH_MAX + 1] = {'0'};
380     PGOProfilerDecoder loader1(path, 4);
381     ASSERT_TRUE(!loader1.LoadAndVerify(checksum));
382 }
383 
HWTEST_F_L0(PGOProfilerTest,PGOProfilerDoubleVM)384 HWTEST_F_L0(PGOProfilerTest, PGOProfilerDoubleVM)
385 {
386     const char *source = R"(
387         .language ECMAScript
388         .function void foo1(any a0, any a1, any a2) {}
389         .function void foo2(any a0, any a1, any a2) {}
390     )";
391     std::vector<MethodLiteral *> methodLiterals {};
392     std::shared_ptr<JSPandaFile> pf = CreateJSPandaFile(source, "ark-profiler5.abc", methodLiterals);
393     EXPECT_EQ(methodLiterals.size(), 2);  // number of methods
394     mkdir("ark-profiler5/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
395     RuntimeOption option;
396     option.SetEnableProfile(true);
397     // outDir is empty
398     option.SetProfileDir("ark-profiler5/");
399     vm_ = JSNApi::CreateJSVM(option);
400     JSHandle<ConstantPool> constPool = vm_->GetFactory()->NewConstantPool(4);
401     constPool->SetJSPandaFile(pf.get());
402     uint32_t checksum = 304293;
403     PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum);
404     ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
405     // worker vm read profile enable from PGOProfilerManager singleton
406     option.SetEnableProfile(false);
407     auto vm2 = JSNApi::CreateJSVM(option);
408     JSHandle<ConstantPool> constPool2 = vm2->GetFactory()->NewConstantPool(4);
409     constPool2->SetJSPandaFile(pf.get());
410     PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum);
411     ASSERT_TRUE(vm2 != nullptr) << "Cannot create Runtime";
412 
413     JSHandle<Method> method = vm2->GetFactory()->NewMethod(methodLiterals[0]);
414     method->SetConstantPool(vm2->GetJSThread(), constPool2.GetTaggedValue());
415     JSHandle<JSFunction> func = vm2->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method);
416     JSHandle<JSTaggedValue> recordName(vm_->GetFactory()->NewFromStdString("test"));
417     func->SetModule(vm2->GetJSThread(), recordName);
418     vm2->GetPGOProfiler()->ProfileCall(JSTaggedValue::VALUE_UNDEFINED, func.GetTaggedType());
419 
420     JSHandle<Method> method1 = vm_->GetFactory()->NewMethod(methodLiterals[0]);
421     JSHandle<Method> method2 = vm_->GetFactory()->NewMethod(methodLiterals[1]);
422     method1->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
423     method2->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
424     JSHandle<JSFunction> func1 = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method1);
425     JSHandle<JSFunction> func2 = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method2);
426     JSHandle<JSTaggedValue> recordName1(vm_->GetFactory()->NewFromStdString("test"));
427     func1->SetModule(vm_->GetJSThread(), recordName);
428     func2->SetModule(vm_->GetJSThread(), recordName);
429     vm_->GetPGOProfiler()->ProfileCall(JSTaggedValue::VALUE_UNDEFINED, func1.GetTaggedType());
430     vm_->GetPGOProfiler()->ProfileCall(JSTaggedValue::VALUE_UNDEFINED, func2.GetTaggedType());
431 
432     JSNApi::DestroyJSVM(vm2);
433     JSNApi::DestroyJSVM(vm_);
434 
435     PGOProfilerDecoder loader("ark-profiler5/profiler", 2);
436     mkdir("ark-profiler5/profiler", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
437     ASSERT_TRUE(!loader.LoadAndVerify(checksum));
438     CString expectRecordName = "test";
439     ASSERT_TRUE(loader.Match(expectRecordName, methodLiterals[1]->GetMethodId()));
440 
441     PGOProfilerDecoder loader1("ark-profiler5/modules.ap", 2);
442 #if defined(SUPPORT_ENABLE_ASM_INTERP)
443     ASSERT_TRUE(loader1.LoadAndVerify(checksum));
444     ASSERT_TRUE(!loader1.Match(expectRecordName, methodLiterals[1]->GetMethodId()));
445 #else
446     ASSERT_TRUE(!loader1.LoadAndVerify(checksum));
447     ASSERT_TRUE(loader1.Match(expectRecordName, methodLiterals[1]->GetMethodId()));
448 #endif
449 
450     unlink("ark-profiler5/modules.ap");
451     rmdir("ark-profiler5/profiler");
452     rmdir("ark-profiler5/");
453 }
454 
HWTEST_F_L0(PGOProfilerTest,PGOProfilerDecoderNoHotMethod)455 HWTEST_F_L0(PGOProfilerTest, PGOProfilerDecoderNoHotMethod)
456 {
457     const char *source = R"(
458         .language ECMAScript
459         .function void foo1(any a0, any a1, any a2) {}
460     )";
461     std::vector<MethodLiteral *> methodLiterals {};
462     std::shared_ptr<JSPandaFile> pf = CreateJSPandaFile(source, "ark-profiler8.abc", methodLiterals);
463     EXPECT_EQ(methodLiterals.size(), 1);  // number of methods
464     mkdir("ark-profiler8/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
465     RuntimeOption option;
466     option.SetEnableProfile(true);
467     option.SetProfileDir("ark-profiler8/");
468     vm_ = JSNApi::CreateJSVM(option);
469     JSHandle<ConstantPool> constPool = vm_->GetFactory()->NewConstantPool(4);
470     constPool->SetJSPandaFile(pf.get());
471     uint32_t checksum = 304293;
472     PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum);
473 
474     JSHandle<Method> method = vm_->GetFactory()->NewMethod(methodLiterals[0]);
475 
476     method->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
477     JSHandle<JSFunction> func = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method);
478     JSHandle<JSTaggedValue> recordName(vm_->GetFactory()->NewFromStdString("test"));
479     func->SetModule(vm_->GetJSThread(), recordName);
480     vm_->GetPGOProfiler()->ProfileCall(JSTaggedValue::VALUE_UNDEFINED, func.GetTaggedType());
481     JSNApi::DestroyJSVM(vm_);
482 
483     PGOProfilerDecoder loader("ark-profiler8/modules.ap", 2);
484     CString expectRecordName = "test";
485 #if defined(SUPPORT_ENABLE_ASM_INTERP)
486     ASSERT_TRUE(loader.LoadAndVerify(checksum));
487     ASSERT_TRUE(!loader.Match(expectRecordName, methodLiterals[0]->GetMethodId()));
488 #else
489     ASSERT_TRUE(!loader.LoadAndVerify(checksum));
490     ASSERT_TRUE(loader.Match(expectRecordName, methodLiterals[0]->GetMethodId()));
491 #endif
492 
493     unlink("ark-profiler8/modules.ap");
494     rmdir("ark-profiler8/");
495 }
496 
HWTEST_F_L0(PGOProfilerTest,PGOProfilerPostTask)497 HWTEST_F_L0(PGOProfilerTest, PGOProfilerPostTask)
498 {
499     std::stringstream sourceStream;
500     sourceStream << "  .language ECMAScript" << std::endl;
501     for (uint32_t funcIdx = 0; funcIdx < 100; funcIdx++) {
502         sourceStream << "  .function void foo" << std::to_string(funcIdx) << "(any a0, any a1, any a2) {}" << std::endl;
503     }
504     std::vector<MethodLiteral *> methodLiterals {};
505     std::shared_ptr<JSPandaFile> pf =
506         CreateJSPandaFile(sourceStream.str().c_str(), "ark-profiler9.abc", methodLiterals);
507     EXPECT_EQ(methodLiterals.size(), 100);  // number of methods
508     mkdir("ark-profiler9/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
509     RuntimeOption option;
510     option.SetEnableProfile(true);
511     option.SetProfileDir("ark-profiler9/");
512     vm_ = JSNApi::CreateJSVM(option);
513     JSHandle<ConstantPool> constPool = vm_->GetFactory()->NewConstantPool(4);
514     constPool->SetJSPandaFile(pf.get());
515     uint32_t checksum = 304293;
516     PGOProfilerManager::GetInstance()->SetApGenMode(ApGenMode::OVERWRITE);
517     PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum);
518 
519     JSHandle<JSTaggedValue> recordName(vm_->GetFactory()->NewFromStdString("test"));
520     for (int i = 61; i < 91; i++) {
521         JSHandle<Method> method = vm_->GetFactory()->NewMethod(methodLiterals[i]);
522         method->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
523         JSHandle<JSFunction> func = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method);
524         func->SetModule(vm_->GetJSThread(), recordName);
525         vm_->GetPGOProfiler()->ProfileCall(JSTaggedValue::VALUE_UNDEFINED, func.GetTaggedType());
526         if (i % 3 == 0) {
527             vm_->GetPGOProfiler()->ProfileCall(JSTaggedValue::VALUE_UNDEFINED, func.GetTaggedType());
528         }
529     }
530 
531     JSNApi::DestroyJSVM(vm_);
532 
533     PGOProfilerDecoder loader("ark-profiler9/modules.ap", 2);
534 #if defined(SUPPORT_ENABLE_ASM_INTERP)
535     ASSERT_TRUE(loader.LoadAndVerify(checksum));
536 #else
537     ASSERT_TRUE(!loader.LoadAndVerify(checksum));
538 #endif
539     CString expectRecordName = "test";
540     for (int i = 0; i < 100; i++) {
541         EntityId methodId = methodLiterals[i]->GetMethodId();
542         loader.MatchAndMarkMethod(expectRecordName, methodLiterals[i]->GetMethodName(pf.get(), methodId), methodId);
543     }
544     for (int i = 61; i < 91; i++) {
545         if (i % 3 == 0) {
546             ASSERT_TRUE(loader.Match(expectRecordName, methodLiterals[i]->GetMethodId()));
547         } else {
548 #if defined(SUPPORT_ENABLE_ASM_INTERP)
549             ASSERT_TRUE(!loader.Match(expectRecordName, methodLiterals[i]->GetMethodId()));
550 #else
551             ASSERT_TRUE(loader.Match(expectRecordName, methodLiterals[i]->GetMethodId()));
552 #endif
553         }
554     }
555 
556     unlink("ark-profiler9/modules.ap");
557     rmdir("ark-profiler9/");
558 }
559 
HWTEST_F_L0(PGOProfilerTest,BinaryToText)560 HWTEST_F_L0(PGOProfilerTest, BinaryToText)
561 {
562     mkdir("ark-profiler7/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
563 
564     std::fstream file("ark-profiler7/modules.ap",
565                       std::fstream::binary | std::fstream::out | std::fstream::in | std::fstream::trunc);
566 
567     PGOProfilerHeader *header = nullptr;
568     PGOProfilerHeader::Build(&header, PGOProfilerHeader::LastSize());
569     std::unique_ptr<PGOPandaFileInfos> pandaFileInfos = std::make_unique<PGOPandaFileInfos>();
570     std::unique_ptr<PGORecordDetailInfos> recordInfos = std::make_unique<PGORecordDetailInfos>(2);
571 
572     RuntimeOption option;
573     vm_ = JSNApi::CreateJSVM(option);
574     ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
575     pandaFileInfos->Sample(0x34556738);
576     std::shared_ptr<MethodLiteral> methodLiteral = std::make_shared<MethodLiteral>(EntityId(61));
577     auto *jsMethod =
578         Method::Cast(vm_->GetFactory()->NewMethod(methodLiteral.get(), MemSpaceType::NON_MOVABLE).GetTaggedValue());
579 
580     ASSERT_TRUE(recordInfos->AddMethod("test", jsMethod, SampleMode::CALL_MODE, 1));
581     ASSERT_FALSE(recordInfos->AddMethod("test", jsMethod, SampleMode::CALL_MODE, 1));
582     ASSERT_FALSE(recordInfos->AddMethod("test", jsMethod, SampleMode::CALL_MODE, 1));
583 
584     pandaFileInfos->ProcessToBinary(file, header->GetPandaInfoSection());
585     recordInfos->ProcessToBinary(nullptr, file, header);
586     header->ProcessToBinary(file);
587     PGOProfilerEncoder::AddChecksum(file);
588     file.close();
589 
590     ASSERT_TRUE(PGOProfilerManager::GetInstance()->BinaryToText(
591         "ark-profiler7/modules.ap", "ark-profiler7/modules.text", 2));
592     JSNApi::DestroyJSVM(vm_);
593     unlink("ark-profiler7/modules.ap");
594     unlink("ark-profiler7/modules.text");
595     rmdir("ark-profiler7");
596 }
597 
HWTEST_F_L0(PGOProfilerTest,TextToBinary)598 HWTEST_F_L0(PGOProfilerTest, TextToBinary)
599 {
600     mkdir("ark-profiler10/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
601 
602     std::ofstream file("ark-profiler10/modules.text");
603     std::string result = "Profiler Version: 0.0.0.1\n";
604     file.write(result.c_str(), result.size());
605     result = "\nPanda file sumcheck list: [ 413775942 ]\n";
606     file.write(result.c_str(), result.size());
607     result = "\nrecordName: [ 1232/3/CALL_MODE/hello, 234/100/HOTNESS_MODE/h#ello1 ]\n";
608     file.write(result.c_str(), result.size());
609     file.close();
610 
611     ASSERT_TRUE(PGOProfilerManager::GetInstance()->TextToBinary("ark-profiler10/modules.text", "ark-profiler10/", 2,
612                                                                 ApGenMode::MERGE));
613 
614     PGOProfilerDecoder loader("ark-profiler10/modules.ap", 2);
615     ASSERT_TRUE(loader.LoadAndVerify(413775942));
616 
617     unlink("ark-profiler10/modules.ap");
618     unlink("ark-profiler10/modules.text");
619     rmdir("ark-profiler10");
620 }
621 
HWTEST_F_L0(PGOProfilerTest,FailResetProfilerInWorker)622 HWTEST_F_L0(PGOProfilerTest, FailResetProfilerInWorker)
623 {
624     const char *source = R"(
625         .language ECMAScript
626         .function void foo1(any a0, any a1, any a2) {}
627     )";
628     std::vector<MethodLiteral *> methodLiterals {};
629     std::shared_ptr<JSPandaFile> pf = CreateJSPandaFile(source, "ark-profiler12.abc", methodLiterals);
630     EXPECT_EQ(methodLiterals.size(), 1);  // number of methods
631     mkdir("ark-profiler12/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
632     RuntimeOption option;
633     // Although enableProfle is set in option, but it will not work when isWorker is set.
634     option.SetEnableProfile(true);
635     option.SetIsWorker();
636     option.SetProfileDir("ark-profiler12/");
637     // PgoProfiler is disabled as default.
638     vm_ = JSNApi::CreateJSVM(option);
639     uint32_t checksum = 304293;
640     PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum);
641     ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
642 
643     JSHandle<Method> method = vm_->GetFactory()->NewMethod(methodLiterals[0]);
644 
645     JSHandle<ConstantPool> constPool = vm_->GetFactory()->NewConstantPool(4);
646     constPool->SetJSPandaFile(pf.get());
647     method->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
648     JSHandle<JSFunction> func = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method);
649     JSHandle<JSTaggedValue> recordName(vm_->GetFactory()->NewFromStdString("test"));
650     func->SetModule(vm_->GetJSThread(), recordName);
651     vm_->GetPGOProfiler()->ProfileCall(JSTaggedValue::VALUE_UNDEFINED, func.GetTaggedType());
652     JSNApi::DestroyJSVM(vm_);
653 
654     // Loader
655     PGOProfilerDecoder loader("ark-profiler12/modules.ap", 2);
656     // path is empty()
657     ASSERT_TRUE(!loader.LoadAndVerify(checksum));
658     CString expectRecordName = "test";
659     ASSERT_TRUE(loader.Match(expectRecordName, methodLiterals[0]->GetMethodId()));
660     rmdir("ark-profiler12/");
661 }
662 
663 #if defined(SUPPORT_ENABLE_ASM_INTERP)
HWTEST_F_L0(PGOProfilerTest,ProfileCallTest)664 HWTEST_F_L0(PGOProfilerTest, ProfileCallTest)
665 {
666     mkdir("ark-profiler13/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
667     const char *targetRecordName = "call_test";
668     std::shared_ptr<JSPandaFile> jsPandaFile = ExecuteAndLoadJSPandaFile("ark-profiler13/", targetRecordName);
669     ASSERT_NE(jsPandaFile, nullptr);
670     uint32_t checksum = jsPandaFile->GetChecksum();
671 
672     // Loader
673     PGOProfilerDecoder decoder("ark-profiler13/modules.ap", 1);
674     PGOProfilerDecoder decoder1("ark-profiler13/modules.ap", 10);
675     PGOProfilerDecoder decoder2("ark-profiler13/modules.ap", 11000);
676     ASSERT_TRUE(decoder.LoadAndVerify(checksum));
677     ASSERT_TRUE(decoder1.LoadAndVerify(checksum));
678     ASSERT_TRUE(decoder2.LoadAndVerify(checksum));
679     auto methodLiterals = jsPandaFile->GetMethodLiteralMap();
680     for (auto iter : methodLiterals) {
681         auto methodLiteral = iter.second;
682         auto methodId = methodLiteral->GetMethodId();
683         auto methodName = methodLiteral->GetMethodName(jsPandaFile.get(), methodId);
684         decoder.MatchAndMarkMethod(targetRecordName, methodName, methodId);
685         decoder1.MatchAndMarkMethod(targetRecordName, methodName, methodId);
686         decoder2.MatchAndMarkMethod(targetRecordName, methodName, methodId);
687         ASSERT_TRUE(decoder.Match(targetRecordName, methodId));
688         if (std::string(methodName) == "Test") {
689             ASSERT_TRUE(!decoder1.Match(targetRecordName, methodId));
690             ASSERT_TRUE(!decoder2.Match(targetRecordName, methodId));
691         } else {
692             ASSERT_TRUE(decoder1.Match(targetRecordName, methodId));
693             ASSERT_TRUE(decoder2.Match(targetRecordName, methodId));
694         }
695     }
696     unlink("ark-profiler13/modules.ap");
697     rmdir("ark-profiler13/");
698 }
699 
HWTEST_F_L0(PGOProfilerTest,UseClassTypeTest)700 HWTEST_F_L0(PGOProfilerTest, UseClassTypeTest)
701 {
702     mkdir("ark-profiler14/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
703     const char *targetRecordName = "class_test";
704     std::shared_ptr<JSPandaFile> jsPandaFile = ExecuteAndLoadJSPandaFile("ark-profiler14/", targetRecordName);
705     ASSERT_NE(jsPandaFile, nullptr);
706     uint32_t checksum = jsPandaFile->GetChecksum();
707 
708     // Loader
709     PGOProfilerDecoder decoder("ark-profiler14/modules.ap", 1);
710     ASSERT_TRUE(decoder.LoadAndVerify(checksum));
711     auto methodLiterals = jsPandaFile->GetMethodLiteralMap();
712     for (auto iter : methodLiterals) {
713         auto methodLiteral = iter.second;
714         auto methodId = methodLiteral->GetMethodId();
715         auto methodName = methodLiteral->GetMethodName(jsPandaFile.get(), methodId);
716         decoder.MatchAndMarkMethod(targetRecordName, methodName, methodId);
717         ASSERT_TRUE(decoder.Match(targetRecordName, methodId));
718         auto callback = [methodName, methodId](uint32_t offset, PGOType *type) {
719             ASSERT_NE(offset, 0);
720             if (type->IsScalarOpType()) {
721             } else if (type->IsRwOpType()) {
722                 auto pgoRWOpType = *reinterpret_cast<PGORWOpType *>(type);
723                 if (std::string(methodName) == "Foot" || std::string(methodName) == "Arm") {
724                     ASSERT_TRUE(pgoRWOpType.GetCount() == 1);
725                     ASSERT_EQ(pgoRWOpType.GetObjectInfo(0).GetClassType(), ClassType(methodId.GetOffset()));
726                 } else if (std::string(methodName) == "foo" || std::string(methodName) == "Body") {
727                     ASSERT_TRUE(pgoRWOpType.GetCount() == 3);
728                 }
729             } else {
730                 ASSERT_TRUE(false);
731             }
732         };
733         decoder.GetTypeInfo(jsPandaFile.get(), targetRecordName, methodLiteral, callback);
734     }
735     unlink("ark-profiler14/modules.ap");
736     rmdir("ark-profiler14/");
737 }
738 
HWTEST_F_L0(PGOProfilerTest,DefineClassTypeTest)739 HWTEST_F_L0(PGOProfilerTest, DefineClassTypeTest)
740 {
741     mkdir("ark-profiler15/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
742     const char *targetRecordName = "class_test";
743     std::shared_ptr<JSPandaFile> jsPandaFile = ExecuteAndLoadJSPandaFile("ark-profiler15/", targetRecordName);
744     ASSERT_NE(jsPandaFile, nullptr);
745     uint32_t checksum = jsPandaFile->GetChecksum();
746 
747     // Loader
748     PGOProfilerDecoder decoder("ark-profiler15/modules.ap", 1);
749     ASSERT_TRUE(decoder.LoadAndVerify(checksum));
750     auto methodLiterals = jsPandaFile->GetMethodLiteralMap();
751     for (auto iter : methodLiterals) {
752         auto methodLiteral = iter.second;
753         auto methodId = methodLiteral->GetMethodId();
754         auto methodName = methodLiteral->GetMethodName(jsPandaFile.get(), methodId);
755         decoder.MatchAndMarkMethod(targetRecordName, methodName, methodId);
756         ASSERT_TRUE(decoder.Match(targetRecordName, methodId));
757         auto callback = [methodName, &decoder, jsPandaFile](uint32_t offset, PGOType *type) {
758             ASSERT_NE(offset, 0);
759             if (type->IsScalarOpType()) {
760                 auto sampleType = *reinterpret_cast<PGOSampleType *>(type);
761                 if (sampleType.IsClassType()) {
762                     ASSERT_EQ(std::string(methodName), "func_main_0");
763                     PGOHClassLayoutDesc *desc;
764                     if (!decoder.GetHClassLayoutDesc(sampleType, &desc)) {
765                         return;
766                     }
767                     ASSERT_EQ(desc->GetCtorLayoutDesc().size(), 3);
768                     ASSERT_EQ(desc->GetPtLayoutDesc().size(), 1);
769                     auto classId = EntityId(sampleType.GetClassType().GetClassType());
770                     auto className = MethodLiteral::GetMethodName(jsPandaFile.get(), classId);
771                     if (std::string(className) == "Arm") {
772                         auto superClassId = EntityId(desc->GetSuperClassType().GetClassType());
773                         auto superClassName = MethodLiteral::GetMethodName(jsPandaFile.get(), superClassId);
774                         ASSERT_EQ(std::string(superClassName), "Body");
775                         ASSERT_EQ(desc->GetLayoutDesc().size(), 3);
776                         ASSERT_EQ(desc->GetLayoutDesc()[0].first, "x");
777                         ASSERT_EQ(desc->GetLayoutDesc()[1].first, "y");
778                         ASSERT_EQ(desc->GetLayoutDesc()[2].first, "t");
779                     } else if (std::string(className) == "Foot") {
780                         auto superClassId = EntityId(desc->GetSuperClassType().GetClassType());
781                         auto superClassName = MethodLiteral::GetMethodName(jsPandaFile.get(), superClassId);
782                         ASSERT_EQ(std::string(superClassName), "Body");
783                         ASSERT_EQ(desc->GetLayoutDesc().size(), 4);
784                         ASSERT_EQ(desc->GetLayoutDesc()[0].first, "x");
785                         ASSERT_EQ(desc->GetLayoutDesc()[1].first, "y");
786                         ASSERT_EQ(desc->GetLayoutDesc()[2].first, "u");
787                         ASSERT_EQ(desc->GetLayoutDesc()[3].first, "v");
788                     } else {
789                         ASSERT_EQ(desc->GetSuperClassType().GetClassType(), 0);
790                         ASSERT_EQ(desc->GetLayoutDesc().size(), 2);
791                         ASSERT_EQ(desc->GetLayoutDesc()[0].first, "x");
792                         ASSERT_EQ(desc->GetLayoutDesc()[1].first, "y");
793                     }
794                 }
795             }
796         };
797         decoder.GetTypeInfo(jsPandaFile.get(), targetRecordName, methodLiteral, callback);
798     }
799     unlink("ark-profiler15/modules.ap");
800     rmdir("ark-profiler15/");
801 }
802 
HWTEST_F_L0(PGOProfilerTest,OpTypeTest)803 HWTEST_F_L0(PGOProfilerTest, OpTypeTest)
804 {
805     mkdir("ark-profiler16/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
806     const char *targetRecordName = "op_type_test";
807     std::shared_ptr<JSPandaFile> jsPandaFile = ExecuteAndLoadJSPandaFile("ark-profiler16/", targetRecordName);
808     ASSERT_NE(jsPandaFile, nullptr);
809     uint32_t checksum = jsPandaFile->GetChecksum();
810 
811     // Loader
812     PGOProfilerDecoder decoder("ark-profiler16/modules.ap", 1);
813     ASSERT_TRUE(decoder.LoadAndVerify(checksum));
814     std::string types[17] = { "1", "1", "1", "5", "4", "4", "4", "4", "4", "4", "5", "4", "4", "1", "4", "5", "1" };
815     int index = 0;
816     auto methodLiterals = jsPandaFile->GetMethodLiteralMap();
817     for (auto iter : methodLiterals) {
818         auto methodLiteral = iter.second;
819         auto methodId = methodLiteral->GetMethodId();
820         auto methodName = methodLiteral->GetMethodName(jsPandaFile.get(), methodId);
821         decoder.MatchAndMarkMethod(targetRecordName, methodName, methodId);
822         ASSERT_TRUE(decoder.Match(targetRecordName, methodId));
823         auto callback = [methodName, types, &index](uint32_t offset, PGOType *type) {
824             ASSERT_NE(offset, 0);
825             if (type->IsScalarOpType()) {
826                 auto sampleType = *reinterpret_cast<PGOSampleType *>(type);
827                 if (sampleType.IsClassType()) {
828                     return;
829                 }
830                 if (std::string(methodName) == "advance") {
831                     ASSERT_EQ(sampleType.GetTypeString(), types[index++]);
832                 }
833             }
834         };
835         decoder.GetTypeInfo(jsPandaFile.get(), targetRecordName, methodLiteral, callback);
836     }
837     unlink("ark-profiler16/modules.ap");
838     rmdir("ark-profiler16/");
839 }
840 
HWTEST_F_L0(PGOProfilerTest,ArrayProfileTest)841 HWTEST_F_L0(PGOProfilerTest, ArrayProfileTest)
842 {
843     mkdir("ark-profiler18/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
844     const char *targetRecordName = "array_test";
845     std::shared_ptr<JSPandaFile> jsPandaFile = ExecuteAndLoadJSPandaFile("ark-profiler18/", targetRecordName);
846     ASSERT_NE(jsPandaFile, nullptr);
847     uint32_t checksum = jsPandaFile->GetChecksum();
848 
849     // Loader
850     PGOProfilerDecoder decoder("ark-profiler18/modules.ap", 1);
851     ASSERT_TRUE(decoder.LoadAndVerify(checksum));
852     auto methodLiterals = jsPandaFile->GetMethodLiteralMap();
853     for (auto iter : methodLiterals) {
854         auto methodLiteral = iter.second;
855         auto methodId = methodLiteral->GetMethodId();
856         auto methodName = methodLiteral->GetMethodName(jsPandaFile.get(), methodId);
857         decoder.MatchAndMarkMethod(targetRecordName, methodName, methodId);
858         ASSERT_TRUE(decoder.Match(targetRecordName, methodId));
859         auto callback = [methodName, &decoder, jsPandaFile](uint32_t offset, PGOType *type) {
860             if (type->IsScalarOpType()) {
861                 auto sampleType = *reinterpret_cast<PGOSampleType *>(type);
862                 if (sampleType.IsClassType()) {
863                     ASSERT_EQ(std::string(methodName), "func_main_0");
864                     PGOHClassLayoutDesc *desc;
865                     if (!decoder.GetHClassLayoutDesc(sampleType, &desc)) {
866                         return;
867                     }
868                     ASSERT_EQ(desc->GetCtorLayoutDesc().size(), 0);
869                     ASSERT_EQ(desc->GetPtLayoutDesc().size(), 0);
870                     ASSERT_EQ(desc->GetLayoutDesc().size(), 1);
871                 }
872             } else if (type->IsRwOpType()) {
873                 auto pgoRWOpType = *reinterpret_cast<PGORWOpType *>(type);
874                 if (std::string(methodName) == "foo") {
875                     ASSERT_TRUE(pgoRWOpType.GetCount() == 3);
876                     auto classType = PGOSampleType(pgoRWOpType.GetObjectInfo(0).GetClassType());
877                     PGOHClassLayoutDesc *desc;
878                     ASSERT_TRUE(decoder.GetHClassLayoutDesc(classType, &desc));
879                     ASSERT_EQ(desc->GetElementsKind(), ElementsKind::NUMBER);
880 
881                     classType = PGOSampleType(pgoRWOpType.GetObjectInfo(1).GetClassType());
882                     ASSERT_TRUE(decoder.GetHClassLayoutDesc(classType, &desc));
883                     ASSERT_EQ(desc->GetElementsKind(), ElementsKind::HOLE_NUMBER);
884 
885                     classType = PGOSampleType(pgoRWOpType.GetObjectInfo(2).GetClassType());
886                     ASSERT_TRUE(decoder.GetHClassLayoutDesc(classType, &desc));
887                     ASSERT_EQ(desc->GetElementsKind(), ElementsKind::HOLE_TAGGED);
888                 } else if (std::string(methodName) == "foo1") {
889                     ASSERT_TRUE(pgoRWOpType.GetCount() == 1);
890                     auto classType = PGOSampleType(pgoRWOpType.GetObjectInfo(0).GetClassType());
891                     PGOHClassLayoutDesc *desc;
892                     ASSERT_TRUE(decoder.GetHClassLayoutDesc(classType, &desc));
893                     ASSERT_EQ(desc->GetElementsKind(), ElementsKind::TAGGED);
894                 }
895             }
896         };
897         decoder.GetTypeInfo(jsPandaFile.get(), targetRecordName, methodLiteral, callback);
898     }
899     unlink("ark-profiler18/modules.ap");
900     rmdir("ark-profiler18/");
901 }
902 #endif
903 
HWTEST_F_L0(PGOProfilerTest,FileConsistencyCheck)904 HWTEST_F_L0(PGOProfilerTest, FileConsistencyCheck)
905 {
906     const char *source = R"(
907         .language ECMAScript
908         .function void foo1(any a0, any a1, any a2) {}
909     )";
910     std::vector<MethodLiteral *> methodLiterals {};
911     std::shared_ptr<JSPandaFile> pf = CreateJSPandaFile(source, "ark-profiler.abc", methodLiterals);
912     EXPECT_EQ(methodLiterals.size(), 1);  // number of methods
913 
914     mkdir("ark-profiler17/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
915     RuntimeOption option;
916     option.SetEnableProfile(true);
917     option.SetProfileDir("ark-profiler17/");
918     vm_ = JSNApi::CreateJSVM(option);
919     JSHandle<ConstantPool> constPool = vm_->GetFactory()->NewConstantPool(4);
920     constPool->SetJSPandaFile(pf.get());
921     uint32_t checksum = 304293;
922     PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum);
923     ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
924 
925     JSHandle<Method> method = vm_->GetFactory()->NewMethod(methodLiterals[0]);
926     method->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
927     JSHandle<JSFunction> func = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method);
928     JSHandle<JSTaggedValue> recordName(vm_->GetFactory()->NewFromStdString("test"));
929     func->SetModule(vm_->GetJSThread(), recordName);
930     vm_->GetPGOProfiler()->SetSaveTimestamp(std::chrono::system_clock::now());
931     vm_->GetPGOProfiler()->ProfileCall(JSTaggedValue::VALUE_UNDEFINED, func.GetTaggedType());
932     JSNApi::DestroyJSVM(vm_);
933 
934     // write to corrupt the ap file's consistency
935     std::ofstream fWriter("ark-profiler17/modules.ap", std::fstream::app);
936 
937     fWriter.write(reinterpret_cast<char *>(&checksum), sizeof(checksum));
938     fWriter.seekp(100);
939     fWriter.write(reinterpret_cast<char *>(&checksum), sizeof(checksum));
940     fWriter.close();
941 
942     // Loader
943     PGOProfilerDecoder loader("ark-profiler17/modules.ap", 2);
944     CString expectRecordName = "test";
945 #if defined(SUPPORT_ENABLE_ASM_INTERP)
946     ASSERT_FALSE(loader.LoadAndVerify(checksum));
947 #else
948     ASSERT_TRUE(!loader.LoadAndVerify(checksum));
949     ASSERT_TRUE(loader.Match(expectRecordName, methodLiterals[0]->GetMethodId()));
950 #endif
951     unlink("ark-profiler17/modules.ap");
952     rmdir("ark-profiler17/");
953 }
954 
955 #if defined(SUPPORT_ENABLE_ASM_INTERP)
HWTEST_F_L0(PGOProfilerTest,MergeApSelfTwice)956 HWTEST_F_L0(PGOProfilerTest, MergeApSelfTwice)
957 {
958     mkdir("ark-profiler18/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
959     const char *targetRecordName = "op_type_test";
960     std::shared_ptr<JSPandaFile> jsPandaFile = ExecuteAndLoadJSPandaFile("ark-profiler18/", targetRecordName);
961     ASSERT_NE(jsPandaFile, nullptr);
962 
963     // Loader
964     PGOProfilerDecoder decoder("ark-profiler18/modules_merge.ap", 1);
965     PGOProfilerDecoder decoderSingle("ark-profiler18/modules.ap", 1);
966     ASSERT_TRUE(PGOProfilerManager::MergeApFiles("ark-profiler18/modules.ap:ark-profiler18/modules.ap",
967                                                  "ark-profiler18/modules_merge.ap", 1, ApGenMode::OVERWRITE));
968     ASSERT_TRUE(decoder.LoadFull());
969     ASSERT_TRUE(decoderSingle.LoadFull());
970 
971     auto doubleCount =
972         decoder.GetRecordDetailInfos().GetRecordInfos().begin()->second->GetMethodInfos().begin()->second->GetCount();
973     auto singleCount = decoderSingle.GetRecordDetailInfos()
974                            .GetRecordInfos()
975                            .begin()
976                            ->second->GetMethodInfos()
977                            .begin()
978                            ->second->GetCount();
979     ASSERT_EQ(doubleCount, singleCount + singleCount);
980 
981     unlink("ark-profiler18/modules.ap");
982     unlink("ark-profiler18/modules_merge.ap");
983     rmdir("ark-profiler18/");
984 }
985 #endif
986 }  // namespace panda::test
987