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 <unordered_map>
22#include <utility>
23
24#include "ecmascript/base/file_header.h"
25#include "ecmascript/elements.h"
26#include "ecmascript/js_symbol.h"
27#include "ecmascript/log_wrapper.h"
28#include "ecmascript/object_factory.h"
29#include "ecmascript/pgo_profiler/ap_file/pgo_file_info.h"
30#include "ecmascript/pgo_profiler/pgo_context.h"
31#include "ecmascript/pgo_profiler/pgo_profiler_encoder.h"
32#include "ecmascript/pgo_profiler/types/pgo_profile_type.h"
33#include "ecmascript/pgo_profiler/types/pgo_profiler_type.h"
34#include "ecmascript/pgo_profiler/pgo_utils.h"
35#include "ecmascript/platform/file.h"
36#include "gtest/gtest.h"
37
38#include "assembler/assembly-emitter.h"
39#include "assembler/assembly-parser.h"
40#include "ecmascript/ecma_vm.h"
41#include "ecmascript/js_thread.h"
42#include "ecmascript/jspandafile/js_pandafile.h"
43#include "ecmascript/jspandafile/js_pandafile_manager.h"
44#include "ecmascript/jspandafile/method_literal.h"
45#include "ecmascript/jspandafile/program_object.h"
46#include "ecmascript/napi/include/jsnapi.h"
47#include "ecmascript/pgo_profiler/ap_file/pgo_method_type_set.h"
48#include "ecmascript/pgo_profiler/pgo_profiler_decoder.h"
49#include "ecmascript/pgo_profiler/pgo_profiler_info.h"
50#include "ecmascript/pgo_profiler/pgo_profiler_manager.h"
51#include "ecmascript/pgo_profiler/tests/pgo_context_mock.h"
52#include "ecmascript/pgo_profiler/tests/pgo_encoder_mock.h"
53#include "ecmascript/tests/test_helper.h"
54#include "ecmascript/napi/include/jsnapi_expo.h"
55
56using namespace panda;
57using namespace panda::ecmascript;
58using namespace panda::ecmascript::pgo;
59using namespace panda::panda_file;
60using namespace panda::pandasm;
61
62namespace panda::test {
63class PGOProfilerTest : public testing::Test {
64public:
65    using ApGenMode = PGOProfilerEncoder::ApGenMode;
66    static void SetUpTestCase()
67    {
68        GTEST_LOG_(INFO) << "SetUpTestCase";
69    }
70
71    static void TearDownTestCase()
72    {
73        GTEST_LOG_(INFO) << "TearDownCase";
74    }
75
76    void SetUp() override
77    {
78        strictMatch_ = PGOProfilerHeader::IsStrictMatch();
79    }
80
81    void TearDown() override
82    {
83        JSPandaFileManager::GetInstance()->RemoveJSPandaFile(pf_.get());
84        vm_ = nullptr;
85        pf_.reset();
86        PGOProfilerManager::GetInstance()->SetDisablePGO(false);
87        PGOProfilerManager::GetInstance()->Destroy();
88        PGOProfilerHeader::SetStrictMatch(strictMatch_);
89    }
90
91protected:
92    void CreateJSPandaFile(const CString filename, std::vector<MethodLiteral *> &methodLiterals)
93    {
94        std::string targetAbcPath = std::string(TARGET_ABC_PATH) + filename.c_str();
95        auto pfPtr = panda_file::OpenPandaFileOrZip(targetAbcPath, panda_file::File::READ_WRITE);
96        JSPandaFileManager *pfManager = JSPandaFileManager::GetInstance();
97        pf_ = pfManager->NewJSPandaFile(pfPtr.release(), filename);
98
99        const File *file = pf_->GetPandaFile();
100        auto classes = pf_->GetClasses();
101
102        for (size_t i = 0; i < classes.Size(); i++) {
103            panda_file::File::EntityId classId(classes[i]);
104            if (!classId.IsValid() || pf_->IsExternal(classId)) {
105                continue;
106            }
107            ClassDataAccessor cda(*file, classId);
108            cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
109                auto *methodLiteral = new MethodLiteral(mda.GetMethodId());
110                methodLiteral->Initialize(pf_.get());
111                pf_->SetMethodLiteralToMap(methodLiteral);
112                methodLiterals.push_back(methodLiteral);
113            });
114        }
115    }
116
117    void CreateJSPandaFile(const char *source, const CString filename, std::vector<MethodLiteral *> &methodLiterals)
118    {
119        Parser parser;
120        const std::string fn = "SRC.abc";  // test file name : "SRC.abc"
121        auto res = parser.Parse(source, fn);
122
123        std::unique_ptr<const File> pfPtr = pandasm::AsmEmitter::Emit(res.Value());
124        JSPandaFileManager *pfManager = JSPandaFileManager::GetInstance();
125        pf_ = pfManager->NewJSPandaFile(pfPtr.release(), filename);
126
127        const File *file = pf_->GetPandaFile();
128        const uint8_t *typeDesc = utf::CStringAsMutf8("L_GLOBAL;");
129        File::EntityId classId = file->GetClassId(typeDesc);
130        EXPECT_TRUE(classId.IsValid());
131
132        ClassDataAccessor cda(*file, classId);
133        cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
134            auto *methodLiteral = new MethodLiteral(mda.GetMethodId());
135            methodLiteral->Initialize(pf_.get());
136            pf_->SetMethodLiteralToMap(methodLiteral);
137            methodLiterals.push_back(methodLiteral);
138        });
139    }
140
141    void ExecuteAndLoadJSPandaFile(std::string profDir, std::string recordName)
142    {
143        RuntimeOption option;
144        option.SetLogLevel(LOG_LEVEL::INFO);
145        option.SetEnableProfile(true);
146        option.SetProfileDir(profDir);
147        vm_ = JSNApi::CreateJSVM(option);
148        JSNApi::EnableUserUncaughtErrorHandler(vm_);
149
150        std::string targetAbcPath = TARGET_ABC_PATH + recordName + ".abc";
151        auto result = JSNApi::Execute(vm_, targetAbcPath, recordName, false);
152        EXPECT_TRUE(result);
153
154        pf_ = JSPandaFileManager::GetInstance()->FindJSPandaFile(CString(targetAbcPath));
155
156        JSNApi::DestroyJSVM(vm_);
157    }
158
159    void ParseRelatedPandaFileMethods(
160        PGOProfilerDecoder &loader,
161        std::unordered_map<std::string, std::unordered_map<std::string, std::vector<PGOMethodId>>> &methodIdInAp)
162    {
163        std::shared_ptr<PGOAbcFilePool> abcFilePool = std::make_shared<PGOAbcFilePool>();
164        ASSERT_TRUE(loader.LoadFull(abcFilePool));
165        for (const auto &recordInfo : loader.GetRecordDetailInfos().GetRecordInfos()) {
166            auto recordProfile = recordInfo.first;
167            ASSERT_EQ(recordProfile.GetKind(), ProfileType::Kind::RecordClassId);
168            if (recordProfile.IsNone()) {
169                continue;
170            }
171            LOG_ECMA(ERROR) << "recordProfile: " << recordProfile.GetTypeString();
172            const auto *recordName =
173                loader.GetRecordDetailInfos().GetRecordPool()->GetName(recordProfile);
174            ASSERT(recordName != nullptr);
175            const auto abcNormalizedDesc =
176                JSPandaFile::GetNormalizedFileDesc(abcFilePool->GetEntry(recordProfile.GetAbcId())->GetData());
177            if (abcNormalizedDesc.empty()) {
178                continue;
179            }
180
181            const auto *info = recordInfo.second;
182            for (const auto &method : info->GetMethodInfos()) {
183                // add ap entry info
184                methodIdInAp[abcNormalizedDesc.c_str()][recordName].emplace_back(method.first);
185            }
186        };
187    }
188
189    void CheckApMethods(
190        std::unordered_map<std::string, std::unordered_map<std::string, std::vector<PGOMethodId>>> &methodIdInAp)
191    {
192        for (auto abcIter = methodIdInAp.begin(); abcIter != methodIdInAp.end();) {
193            std::string fileName(abcIter->first.c_str());
194            auto lastDirToken = fileName.find_last_of('/');
195            if (lastDirToken != std::string::npos) {
196                fileName = fileName.substr(lastDirToken + 1);
197            }
198            std::unordered_map<std::string, std::vector<PGOMethodId>> &recordMethodList = abcIter->second;
199            CheckApMethodsInApFiles(fileName, recordMethodList);
200            if (recordMethodList.empty()) {
201                abcIter = methodIdInAp.erase(abcIter);
202            } else {
203                abcIter++;
204            }
205        }
206        ASSERT_TRUE(methodIdInAp.empty());
207    }
208
209    void CheckApMethodsInApFiles(const std::string &fileName,
210                                 std::unordered_map<std::string, std::vector<PGOMethodId>> &recordMethodList)
211    {
212        std::vector<MethodLiteral *> methodLiterals {};
213        CreateJSPandaFile(fileName.c_str(), methodLiterals);
214        for (auto &methodLiteral : methodLiterals) {
215            auto methodName = MethodLiteral::GetRecordName(pf_.get(), methodLiteral->GetMethodId());
216            auto recordEntry = recordMethodList.find(methodName.c_str());
217            if (recordEntry == recordMethodList.end()) {
218                continue;
219            }
220            for (size_t index = 0; index < recordEntry->second.size(); ++index) {
221                if (!(recordEntry->second.at(index) == methodLiteral->GetMethodId())) {
222                    continue;
223                }
224                // Remove matched entry
225                recordEntry->second.erase(recordEntry->second.begin() + index);
226                if (recordEntry->second.empty()) {
227                    recordEntry = recordMethodList.erase(recordEntry);
228                }
229                break;
230            }
231        }
232    }
233
234    static constexpr uint32_t DECODER_THRESHOLD = 2;
235    EcmaVM *vm_ = nullptr;
236    bool strictMatch_ = false;
237    std::shared_ptr<JSPandaFile> pf_;
238};
239
240HWTEST_F_L0(PGOProfilerTest, Sample)
241{
242    std::vector<MethodLiteral *> methodLiterals {};
243    CreateJSPandaFile("sample_test.abc", methodLiterals);
244
245    mkdir("ark-profiler/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
246    RuntimeOption option;
247    option.SetEnableProfile(true);
248    option.SetProfileDir("ark-profiler/");
249    vm_ = JSNApi::CreateJSVM(option);
250    vm_->GetJSThread()->ManagedCodeBegin();
251    JSHandle<ConstantPool> constPool = vm_->GetFactory()->NewSConstantPool(4);
252    constPool->SetJSPandaFile(pf_.get());
253    uint32_t checksum = 304293;
254    PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum, "ark-profiler.abc");
255    ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
256
257    JSHandle<Method> method = vm_->GetFactory()->NewSMethod(methodLiterals[0]);
258    method->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
259    JSHandle<JSTaggedValue> recordName(vm_->GetFactory()->NewFromStdString("test"));
260    JSHandle<JSFunction> func = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method);
261    func->SetModule(vm_->GetJSThread(), recordName);
262    vm_->GetPGOProfiler()->SetSaveTimestamp(std::chrono::system_clock::now());
263    vm_->GetJSThread()->ManagedCodeEnd();
264    JSNApi::DestroyJSVM(vm_);
265    // Loader
266    PGOProfilerDecoder loader("ark-profiler/modules.ap", DECODER_THRESHOLD);
267    CString expectRecordName = "sample_test";
268#if defined(SUPPORT_ENABLE_ASM_INTERP)
269    ASSERT_TRUE(loader.LoadAndVerify(checksum));
270    ASSERT_TRUE(!loader.Match(pf_.get(), expectRecordName, methodLiterals[0]->GetMethodId()));
271#else
272    ASSERT_TRUE(!loader.LoadAndVerify(checksum));
273    ASSERT_TRUE(loader.Match(pf_.get(), expectRecordName, methodLiterals[0]->GetMethodId()));
274#endif
275    unlink("ark-profiler/modules.ap");
276    rmdir("ark-profiler/");
277}
278
279HWTEST_F_L0(PGOProfilerTest, Sample1)
280{
281    mkdir("ark-profiler1/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
282    std::vector<MethodLiteral *> methodLiterals {};
283    CreateJSPandaFile("sample_test.abc", methodLiterals);
284
285    mkdir("ark-profiler1/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
286    RuntimeOption option;
287    option.SetEnableProfile(true);
288    option.SetProfileDir("ark-profiler1/");
289    vm_ = JSNApi::CreateJSVM(option);
290    vm_->GetJSThread()->ManagedCodeBegin();
291    JSHandle<ConstantPool> constPool = vm_->GetFactory()->NewSConstantPool(4);
292    constPool->SetJSPandaFile(pf_.get());
293    uint32_t checksum = 304293;
294    PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum, "ark-profiler1.abc");
295    ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
296
297    JSHandle<Method> method = vm_->GetFactory()->NewSMethod(methodLiterals[0]);
298    JSHandle<Method> method1 = vm_->GetFactory()->NewSMethod(methodLiterals[1]);
299    JSHandle<Method> method2 = vm_->GetFactory()->NewSMethod(methodLiterals[2]);
300    method->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
301    method1->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
302    method2->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
303
304    JSHandle<JSFunction> func = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method);
305    JSHandle<JSFunction> func1 = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method1);
306    JSHandle<JSFunction> func2 = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method2);
307    JSHandle<JSTaggedValue> recordName(vm_->GetFactory()->NewFromStdString("test"));
308    func->SetModule(vm_->GetJSThread(), recordName);
309    func1->SetModule(vm_->GetJSThread(), recordName);
310    func2->SetModule(vm_->GetJSThread(), recordName);
311    vm_->GetJSThread()->ManagedCodeEnd();
312    JSNApi::DestroyJSVM(vm_);
313
314    // Loader
315    PGOProfilerDecoder loader("ark-profiler1/modules.ap", DECODER_THRESHOLD);
316    CString expectRecordName = "sample_test";
317#if defined(SUPPORT_ENABLE_ASM_INTERP)
318    ASSERT_TRUE(loader.LoadAndVerify(checksum));
319    for (uint32_t idx = 0; idx < 3; idx++) {
320        loader.MatchAndMarkMethod(pf_.get(), expectRecordName,
321                                 methodLiterals[idx]->GetMethodName(pf_.get(), methodLiterals[idx]->GetMethodId()),
322                                 methodLiterals[idx]->GetMethodId());
323    }
324    ASSERT_TRUE(!loader.Match(pf_.get(), expectRecordName, methodLiterals[0]->GetMethodId()));
325    ASSERT_TRUE(!loader.Match(pf_.get(), expectRecordName, methodLiterals[2]->GetMethodId()));
326    ASSERT_TRUE(!loader.Match(pf_.get(), expectRecordName, methodLiterals[1]->GetMethodId()));
327#else
328    ASSERT_TRUE(!loader.LoadAndVerify(checksum));
329    ASSERT_TRUE(loader.Match(pf_.get(), expectRecordName, methodLiterals[1]->GetMethodId()));
330#endif
331    unlink("ark-profiler1/modules.ap");
332    rmdir("ark-profiler1/");
333}
334
335HWTEST_F_L0(PGOProfilerTest, Sample2)
336{
337    mkdir("ark-profiler2/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
338    std::vector<MethodLiteral *> methodLiterals {};
339    CreateJSPandaFile("sample_test.abc", methodLiterals);
340
341    mkdir("ark-profiler2/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
342    RuntimeOption option;
343    option.SetEnableProfile(true);
344    option.SetProfileDir("ark-profiler2/");
345    vm_ = JSNApi::CreateJSVM(option);
346    vm_->GetJSThread()->ManagedCodeBegin();
347    JSHandle<ConstantPool> constPool = vm_->GetFactory()->NewSConstantPool(4);
348    constPool->SetJSPandaFile(pf_.get());
349    ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
350    uint32_t checksum = 304293;
351    PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum, "ark-profiler2.abc");
352
353    JSHandle<Method> method = vm_->GetFactory()->NewSMethod(methodLiterals[0]);
354    JSHandle<Method> method1 = vm_->GetFactory()->NewSMethod(methodLiterals[1]);
355
356    method->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
357    method1->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
358    JSHandle<JSFunction> func = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method);
359    JSHandle<JSTaggedValue> recordName(vm_->GetFactory()->NewFromStdString("test"));
360    func->SetModule(vm_->GetJSThread(), recordName);
361    JSHandle<JSFunction> func1 = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method1);
362    JSHandle<JSTaggedValue> recordName1(vm_->GetFactory()->NewFromStdString("test1"));
363    func1->SetModule(vm_->GetJSThread(), recordName1);
364    vm_->GetJSThread()->ManagedCodeEnd();
365    JSNApi::DestroyJSVM(vm_);
366
367    // Loader
368    PGOProfilerDecoder loader("ark-profiler2/modules.ap", DECODER_THRESHOLD);
369    CString expectRecordName = "sample_test";
370    CString expectRecordName1 = "sample_test";
371#if defined(SUPPORT_ENABLE_ASM_INTERP)
372    ASSERT_TRUE(loader.LoadAndVerify(checksum));
373    for (uint32_t idx = 0; idx < 2; idx++) {
374        loader.MatchAndMarkMethod(pf_.get(), expectRecordName,
375                                 methodLiterals[idx]->GetMethodName(pf_.get(), methodLiterals[idx]->GetMethodId()),
376                                 methodLiterals[idx]->GetMethodId());
377        loader.MatchAndMarkMethod(pf_.get(), expectRecordName1,
378                                 methodLiterals[idx]->GetMethodName(pf_.get(), methodLiterals[idx]->GetMethodId()),
379                                 methodLiterals[idx]->GetMethodId());
380    }
381    ASSERT_TRUE(!loader.Match(pf_.get(), expectRecordName, methodLiterals[0]->GetMethodId()));
382    ASSERT_TRUE(!loader.Match(pf_.get(), expectRecordName1, methodLiterals[1]->GetMethodId()));
383#else
384    ASSERT_TRUE(!loader.LoadAndVerify(checksum));
385    ASSERT_TRUE(loader.Match(pf_.get(), expectRecordName, methodLiterals[0]->GetMethodId()));
386    ASSERT_TRUE(loader.Match(pf_.get(), expectRecordName1, methodLiterals[1]->GetMethodId()));
387#endif
388    unlink("ark-profiler2/modules.ap");
389    rmdir("ark-profiler2/");
390}
391
392HWTEST_F_L0(PGOProfilerTest, DisEnableSample)
393{
394    std::vector<MethodLiteral *> methodLiterals {};
395    CreateJSPandaFile("sample_test.abc", methodLiterals);
396    EXPECT_GE(methodLiterals.size(), 1);
397    mkdir("ark-profiler3/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
398    RuntimeOption option;
399    option.SetEnableProfile(false);
400    option.SetProfileDir("ark-profiler3/");
401    vm_ = JSNApi::CreateJSVM(option);
402    vm_->GetJSThread()->ManagedCodeBegin();
403    JSPandaFileManager::GetInstance()->AddJSPandaFile(pf_);
404    JSHandle<ConstantPool> constPool = vm_->GetFactory()->NewSConstantPool(4);
405    constPool->SetJSPandaFile(pf_.get());
406    uint32_t checksum = pf_->GetChecksum();
407    PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum, "sample_test.abc");
408    ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
409
410    JSHandle<Method> method = vm_->GetFactory()->NewSMethod(methodLiterals[0]);
411
412    method->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
413    JSHandle<JSFunction> func = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method);
414    JSHandle<JSTaggedValue> recordName(vm_->GetFactory()->NewFromStdString("sample_test"));
415    func->SetModule(vm_->GetJSThread(), recordName);
416    vm_->GetJSThread()->ManagedCodeEnd();
417    JSNApi::DestroyJSVM(vm_);
418
419    // Loader
420    ASSERT_FALSE(FileExist("ark-profiler3/modules.ap"));
421    PGOProfilerDecoder loader("ark-profiler3/modules.ap", DECODER_THRESHOLD);
422    ASSERT_TRUE(!loader.LoadAndVerify(checksum));
423    CString expectRecordName = "sample_test";
424    ASSERT_TRUE(loader.Match(pf_.get(), expectRecordName, methodLiterals[0]->GetMethodId()));
425    rmdir("ark-profiler3/");
426}
427
428HWTEST_F_L0(PGOProfilerTest, PGOProfilerManagerInvalidPath)
429{
430    RuntimeOption option;
431    option.SetEnableProfile(true);
432    option.SetProfileDir("ark-profiler4");
433    vm_ = JSNApi::CreateJSVM(option);
434    ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
435    JSNApi::DestroyJSVM(vm_);
436}
437
438HWTEST_F_L0(PGOProfilerTest, PGOProfilerManagerInitialize)
439{
440    RuntimeOption option;
441    option.SetEnableProfile(true);
442    // outDir is empty
443    option.SetProfileDir("");
444    vm_ = JSNApi::CreateJSVM(option);
445    ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
446
447    JSNApi::DestroyJSVM(vm_);
448}
449
450HWTEST_F_L0(PGOProfilerTest, PGOProfilerManagerSample)
451{
452    RuntimeOption option;
453    option.SetEnableProfile(true);
454    char currentPath[PATH_MAX + 2];
455    if (memset_s(currentPath, PATH_MAX, 1, PATH_MAX) != EOK) {
456        ASSERT_TRUE(false);
457    }
458    currentPath[PATH_MAX + 1] = '\0';
459    option.SetProfileDir(currentPath);
460    vm_ = JSNApi::CreateJSVM(option);
461    vm_->GetJSThread()->ManagedCodeBegin();
462    uint32_t checksum = 304293;
463    PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum, "");
464    ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
465
466    // RecordName is hole
467    MethodLiteral *methodLiteral = new MethodLiteral(EntityId(61));
468    JSHandle<Method> method = vm_->GetFactory()->NewSMethod(methodLiteral);
469    JSHandle<JSFunction> func = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method);
470    func->SetModule(vm_->GetJSThread(), JSTaggedValue::Hole());
471    vm_->GetJSThread()->ManagedCodeEnd();
472    JSNApi::DestroyJSVM(vm_);
473
474    PGOProfilerDecoder loader("", DECODER_THRESHOLD);
475    // path is empty()
476    ASSERT_TRUE(loader.LoadAndVerify(checksum));
477    // path size greater than PATH_MAX
478    char path[PATH_MAX + 1] = {'0'};
479    PGOProfilerDecoder loader1(path, 4);
480    ASSERT_TRUE(!loader1.LoadAndVerify(checksum));
481}
482
483HWTEST_F_L0(PGOProfilerTest, PGOProfilerDoubleVM)
484{
485    mkdir("ark-profiler5/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
486    std::vector<MethodLiteral *> methodLiterals {};
487    CreateJSPandaFile("sample_test.abc", methodLiterals);
488    EXPECT_GE(methodLiterals.size(), 2);  // number of methods
489    mkdir("ark-profiler5/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
490    RuntimeOption option;
491    option.SetEnableProfile(true);
492    // outDir is empty
493    option.SetProfileDir("ark-profiler5/");
494    vm_ = JSNApi::CreateJSVM(option);
495    vm_->GetJSThread()->ManagedCodeBegin();
496    JSPandaFileManager::GetInstance()->AddJSPandaFile(pf_);
497    JSHandle<ConstantPool> constPool = vm_->GetFactory()->NewSConstantPool(4);
498    constPool->SetJSPandaFile(pf_.get());
499    uint32_t checksum = 304293;
500    PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum, "sample_test.abc");
501    ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
502    // worker vm read profile enable from PGOProfilerManager singleton
503    option.SetEnableProfile(false);
504
505    std::thread t1([&]() {
506        auto vm2 = JSNApi::CreateJSVM(option);
507        vm2->GetJSThread()->ManagedCodeBegin();
508        JSHandle<ConstantPool> constPool2 = vm2->GetFactory()->NewSConstantPool(4);
509        constPool2->SetJSPandaFile(pf_.get());
510        PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum, "sample_test.abc");
511        ASSERT_TRUE(vm2 != nullptr) << "Cannot create Runtime";
512
513        JSHandle<Method> method = vm2->GetFactory()->NewSMethod(methodLiterals[0]);
514        method->SetConstantPool(vm2->GetJSThread(), constPool2.GetTaggedValue());
515        JSHandle<JSFunction> func = vm2->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method);
516        JSHandle<JSTaggedValue> recordName(vm2->GetFactory()->NewFromStdString("sample_test"));
517        func->SetModule(vm2->GetJSThread(), recordName);
518        vm2->GetJSThread()->ManagedCodeEnd();
519        JSNApi::DestroyJSVM(vm2);
520    });
521    {
522        ThreadSuspensionScope scope(vm_->GetJSThread());
523        t1.join();
524    }
525    JSHandle<JSTaggedValue> recordName(vm_->GetFactory()->NewFromStdString("sample_test"));
526    JSHandle<Method> method1 = vm_->GetFactory()->NewSMethod(methodLiterals[0]);
527    JSHandle<Method> method2 = vm_->GetFactory()->NewSMethod(methodLiterals[1]);
528    method1->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
529    method2->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
530    JSHandle<JSFunction> func1 = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method1);
531    JSHandle<JSFunction> func2 = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method2);
532    JSHandle<JSTaggedValue> recordName1(vm_->GetFactory()->NewFromStdString("sample_test"));
533    func1->SetModule(vm_->GetJSThread(), recordName);
534    func2->SetModule(vm_->GetJSThread(), recordName);
535
536    vm_->GetJSThread()->ManagedCodeEnd();
537    JSNApi::DestroyJSVM(vm_);
538
539    PGOProfilerDecoder loader("ark-profiler5/profiler", DECODER_THRESHOLD);
540    mkdir("ark-profiler5/profiler", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
541    ASSERT_TRUE(!loader.LoadAndVerify(checksum));
542    CString expectRecordName = "sample_test";
543    ASSERT_TRUE(loader.Match(pf_.get(), expectRecordName, methodLiterals[1]->GetMethodId()));
544
545    PGOProfilerDecoder loader1("ark-profiler5/modules.ap", DECODER_THRESHOLD);
546#if defined(SUPPORT_ENABLE_ASM_INTERP)
547    ASSERT_TRUE(loader1.LoadAndVerify(checksum));
548    ASSERT_TRUE(!loader1.Match(pf_.get(), expectRecordName, methodLiterals[1]->GetMethodId()));
549#else
550    ASSERT_TRUE(!loader1.LoadAndVerify(checksum));
551    ASSERT_TRUE(loader1.Match(pf_.get(), expectRecordName, methodLiterals[1]->GetMethodId()));
552#endif
553
554    unlink("ark-profiler5/modules.ap");
555    rmdir("ark-profiler5/profiler");
556    rmdir("ark-profiler5/");
557}
558
559HWTEST_F_L0(PGOProfilerTest, PGOProfilerDecoderNoHotMethod)
560{
561    std::vector<MethodLiteral *> methodLiterals {};
562    CreateJSPandaFile("sample_test.abc", methodLiterals);
563    EXPECT_GE(methodLiterals.size(), 1);  // number of methods
564    mkdir("ark-profiler8/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
565    RuntimeOption option;
566    option.SetEnableProfile(true);
567    option.SetProfileDir("ark-profiler8/");
568    vm_ = JSNApi::CreateJSVM(option);
569    vm_->GetJSThread()->ManagedCodeBegin();
570    JSPandaFileManager::GetInstance()->AddJSPandaFile(pf_);
571    JSHandle<ConstantPool> constPool = vm_->GetFactory()->NewSConstantPool(4);
572    constPool->SetJSPandaFile(pf_.get());
573    uint32_t checksum = pf_->GetChecksum();
574    PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum, "sample_test.abc");
575
576    JSHandle<Method> method = vm_->GetFactory()->NewSMethod(methodLiterals[0]);
577
578    method->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
579    JSHandle<JSFunction> func = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method);
580    JSHandle<JSTaggedValue> recordName(vm_->GetFactory()->NewFromStdString("sample_test"));
581    func->SetModule(vm_->GetJSThread(), recordName);
582    vm_->GetJSThread()->ManagedCodeEnd();
583    JSNApi::DestroyJSVM(vm_);
584
585    PGOProfilerDecoder loader("ark-profiler8/modules.ap", DECODER_THRESHOLD);
586    CString expectRecordName = "sample_test";
587#if defined(SUPPORT_ENABLE_ASM_INTERP)
588    ASSERT_TRUE(loader.LoadAndVerify(checksum));
589    ASSERT_TRUE(!loader.Match(pf_.get(), expectRecordName, methodLiterals[0]->GetMethodId()));
590#else
591    ASSERT_TRUE(!loader.LoadAndVerify(checksum));
592    ASSERT_TRUE(loader.Match(pf_.get(), expectRecordName, methodLiterals[0]->GetMethodId()));
593#endif
594
595    unlink("ark-profiler8/modules.ap");
596    rmdir("ark-profiler8/");
597}
598
599HWTEST_F_L0(PGOProfilerTest, PGOProfilerPostTask)
600{
601    std::stringstream sourceStream;
602    sourceStream << "  .language ECMAScript" << std::endl;
603    for (uint32_t funcIdx = 0; funcIdx < 100; funcIdx++) {
604        sourceStream << "  .function void foo" << std::to_string(funcIdx) << "(any a0, any a1, any a2) {}" << std::endl;
605    }
606    std::vector<MethodLiteral *> methodLiterals {};
607    CreateJSPandaFile(sourceStream.str().c_str(), "ark-profiler9.abc", methodLiterals);
608    EXPECT_EQ(methodLiterals.size(), 100);  // number of methods
609    mkdir("ark-profiler9/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
610    RuntimeOption option;
611    option.SetEnableProfile(true);
612    option.SetProfileDir("ark-profiler9/");
613    vm_ = JSNApi::CreateJSVM(option);
614    vm_->GetJSThread()->ManagedCodeBegin();
615    JSPandaFileManager::GetInstance()->AddJSPandaFile(pf_);
616    JSHandle<ConstantPool> constPool = vm_->GetFactory()->NewSConstantPool(4);
617    constPool->SetJSPandaFile(pf_.get());
618    uint32_t checksum = 304293;
619    PGOProfilerManager::GetInstance()->SetApGenMode(ApGenMode::OVERWRITE);
620    PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum, "ark-profiler9.abc");
621
622    JSHandle<JSTaggedValue> recordName(vm_->GetFactory()->NewFromStdString("ark-profiler9.abc"));
623    for (int i = 61; i < 91; i++) {
624        JSHandle<Method> method = vm_->GetFactory()->NewSMethod(methodLiterals[i]);
625        method->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
626        JSHandle<JSFunction> func = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method);
627        func->SetModule(vm_->GetJSThread(), recordName);
628    }
629
630    vm_->GetJSThread()->ManagedCodeEnd();
631    JSNApi::DestroyJSVM(vm_);
632
633    PGOProfilerDecoder loader("ark-profiler9/modules.ap", DECODER_THRESHOLD);
634#if defined(SUPPORT_ENABLE_ASM_INTERP)
635    ASSERT_TRUE(loader.LoadAndVerify(checksum));
636#else
637    ASSERT_TRUE(!loader.LoadAndVerify(checksum));
638#endif
639    CString expectRecordName = "ark-profiler9.abc";
640    for (int i = 0; i < 100; i++) {
641        EntityId methodId = methodLiterals[i]->GetMethodId();
642        loader.MatchAndMarkMethod(pf_.get(), expectRecordName,
643                                  methodLiterals[i]->GetMethodName(pf_.get(), methodId), methodId);
644    }
645    for (int i = 61; i < 91; i++) {
646#if defined(SUPPORT_ENABLE_ASM_INTERP)
647        if (i % 3 == 0) {
648            ASSERT_TRUE(!loader.Match(pf_.get(), expectRecordName, methodLiterals[i]->GetMethodId()));
649        } else {
650            ASSERT_TRUE(!loader.Match(pf_.get(), expectRecordName, methodLiterals[i]->GetMethodId()));
651#else
652        if (i % 3 == 0) {
653            ASSERT_TRUE(loader.Match(pf_.get(), expectRecordName, methodLiterals[i]->GetMethodId()));
654        } else {
655            ASSERT_TRUE(loader.Match(pf_.get(), expectRecordName, methodLiterals[i]->GetMethodId()));
656#endif
657        }
658    }
659
660    unlink("ark-profiler9/modules.ap");
661    rmdir("ark-profiler9/");
662}
663
664HWTEST_F_L0(PGOProfilerTest, TextToBinary)
665{
666    mkdir("ark-profiler10/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
667
668    std::ofstream file("ark-profiler10/modules.text");
669    std::string result = "Profiler Version: 0.0.0.1\n";
670    file.write(result.c_str(), result.size());
671    result = "\nPanda file sumcheck list: [ 413775942 ]\n";
672    file.write(result.c_str(), result.size());
673    result = "\nrecordName: [ 1232/3/CALL_MODE/hello, 234/100/HOTNESS_MODE/h#ello1 ]\n";
674    file.write(result.c_str(), result.size());
675    file.close();
676
677    PGOProfilerHeader::SetStrictMatch(false);
678    ASSERT_TRUE(PGOProfilerManager::GetInstance()->TextToBinary("ark-profiler10/modules.text", "ark-profiler10/", 2,
679                                                                ApGenMode::OVERWRITE));
680
681    PGOProfilerDecoder loader("ark-profiler10/modules.ap", DECODER_THRESHOLD);
682    ASSERT_TRUE(loader.LoadAndVerify(413775942));
683
684    unlink("ark-profiler10/modules.ap");
685    unlink("ark-profiler10/modules.text");
686    rmdir("ark-profiler10");
687}
688
689HWTEST_F_L0(PGOProfilerTest, FailResetProfilerInWorker)
690{
691    std::vector<MethodLiteral *> methodLiterals {};
692    CreateJSPandaFile("sample_test.abc", methodLiterals);
693    EXPECT_GE(methodLiterals.size(), 1);  // number of methods
694    mkdir("ark-profiler12/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
695    RuntimeOption option;
696    // Although enableProfile is set in option, but it will not work when isWorker is set.
697    option.SetEnableProfile(true);
698    option.SetIsWorker();
699    option.SetProfileDir("ark-profiler12/");
700    // PgoProfiler is disabled as default.
701    vm_ = JSNApi::CreateJSVM(option);
702    vm_->GetJSThread()->ManagedCodeBegin();
703    JSPandaFileManager::GetInstance()->AddJSPandaFile(pf_);
704    uint32_t checksum = pf_->GetChecksum();
705    PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum, "sample_test.abc");
706    ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
707
708    JSHandle<Method> method = vm_->GetFactory()->NewSMethod(methodLiterals[0]);
709
710    JSHandle<ConstantPool> constPool = vm_->GetFactory()->NewSConstantPool(4);
711    constPool->SetJSPandaFile(pf_.get());
712    method->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
713    JSHandle<JSFunction> func = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method);
714    JSHandle<JSTaggedValue> recordName(vm_->GetFactory()->NewFromStdString("sample_test"));
715    func->SetModule(vm_->GetJSThread(), recordName);
716    vm_->GetJSThread()->ManagedCodeEnd();
717    JSNApi::DestroyJSVM(vm_);
718
719    // Loader
720    ASSERT_FALSE(FileExist("ark-profiler12/modules.ap"));
721    PGOProfilerDecoder loader("ark-profiler12/modules.ap", DECODER_THRESHOLD);
722    ASSERT_TRUE(!loader.LoadAndVerify(checksum));
723    CString expectRecordName = "sample_test";
724    ASSERT_TRUE(loader.Match(pf_.get(), expectRecordName, methodLiterals[0]->GetMethodId()));
725    rmdir("ark-profiler12/");
726}
727
728#if defined(SUPPORT_ENABLE_ASM_INTERP)
729HWTEST_F_L0(PGOProfilerTest, ProfileCallTest)
730{
731    mkdir("ark-profiler13/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
732    const char *targetRecordName = "call_test";
733    ExecuteAndLoadJSPandaFile("ark-profiler13/", targetRecordName);
734    ASSERT_NE(pf_, nullptr);
735    uint32_t checksum = pf_->GetChecksum();
736
737    // Loader
738    PGOProfilerDecoder decoder("ark-profiler13/modules.ap", 1);
739    PGOProfilerDecoder decoder1("ark-profiler13/modules.ap", 10);
740    PGOProfilerDecoder decoder2("ark-profiler13/modules.ap", 11000);
741    ASSERT_TRUE(decoder.LoadAndVerify(checksum));
742    ASSERT_TRUE(decoder1.LoadAndVerify(checksum));
743    ASSERT_TRUE(decoder2.LoadAndVerify(checksum));
744    auto methodLiterals = pf_->GetMethodLiteralMap();
745    for (auto iter : methodLiterals) {
746        auto methodLiteral = iter.second;
747        auto methodId = methodLiteral->GetMethodId();
748        auto methodName = methodLiteral->GetMethodName(pf_.get(), methodId);
749        decoder.MatchAndMarkMethod(pf_.get(), targetRecordName, methodName, methodId);
750        decoder1.MatchAndMarkMethod(pf_.get(), targetRecordName, methodName, methodId);
751        decoder2.MatchAndMarkMethod(pf_.get(), targetRecordName, methodName, methodId);
752        // ASSERT_TRUE(decoder.Match(pf_.get(), targetRecordName, methodId))
753        if (std::string(methodName) == "Test") {
754            ASSERT_TRUE(decoder1.Match(pf_.get(), targetRecordName, methodId));
755            ASSERT_TRUE(decoder2.Match(pf_.get(), targetRecordName, methodId));
756        } else {
757            // ASSERT_TRUE(decoder1.Match(pf_.get(), targetRecordName, methodId))
758            // ASSERT_TRUE(decoder2.Match(pf_.get(), targetRecordName, methodId))
759        }
760    }
761    unlink("ark-profiler13/modules.ap");
762    rmdir("ark-profiler13/");
763}
764
765HWTEST_F_L0(PGOProfilerTest, UseClassTypeTest)
766{
767    mkdir("ark-profiler14/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
768    const char *targetRecordName = "class_test";
769    ExecuteAndLoadJSPandaFile("ark-profiler14/", targetRecordName);
770    ASSERT_NE(pf_, nullptr);
771    uint32_t checksum = pf_->GetChecksum();
772
773    // Loader
774    PGOProfilerDecoder decoder("ark-profiler14/modules.ap", 1);
775    ASSERT_TRUE(decoder.LoadAndVerify(checksum));
776    auto methodLiterals = pf_->GetMethodLiteralMap();
777    for (auto iter : methodLiterals) {
778        auto methodLiteral = iter.second;
779        auto methodId = methodLiteral->GetMethodId();
780        auto methodName = methodLiteral->GetMethodName(pf_.get(), methodId);
781        decoder.MatchAndMarkMethod(pf_.get(), targetRecordName, methodName, methodId);
782        ASSERT_TRUE(!decoder.Match(pf_.get(), targetRecordName, methodId));
783        auto callback = [methodName](uint32_t offset, const PGOType *type) {
784            ASSERT_NE(offset, 0);
785            if (type->IsScalarOpType()) {
786            } else if (type->IsRwOpType()) {
787                auto pgoRWOpType = *reinterpret_cast<const PGORWOpType *>(type);
788                if (std::string(methodName) == "Foot" || std::string(methodName) == "Arm") {
789                    ASSERT_TRUE(pgoRWOpType.GetCount() == 1);
790                } else if (std::string(methodName) == "foo" || std::string(methodName) == "Body") {
791                    ASSERT_TRUE(pgoRWOpType.GetCount() == 3);
792                }
793            } else {
794                ASSERT_TRUE(true);
795            }
796        };
797        decoder.GetTypeInfo(pf_.get(), targetRecordName, methodLiteral,
798                            callback);
799    }
800    unlink("ark-profiler14/modules.ap");
801    rmdir("ark-profiler14/");
802}
803
804HWTEST_F_L0(PGOProfilerTest, DefineClassTypeTest)
805{
806    mkdir("ark-profiler15/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
807    const char *targetRecordName = "class_test";
808    ExecuteAndLoadJSPandaFile("ark-profiler15/", targetRecordName);
809    ASSERT_NE(pf_, nullptr);
810    uint32_t checksum = pf_->GetChecksum();
811
812    // Loader
813    PGOProfilerDecoder decoder("ark-profiler15/modules.ap", 1);
814    ASSERT_TRUE(decoder.LoadAndVerify(checksum));
815    auto methodLiterals = pf_->GetMethodLiteralMap();
816    for (auto iter : methodLiterals) {
817        auto methodLiteral = iter.second;
818        auto methodId = methodLiteral->GetMethodId();
819        auto methodName = methodLiteral->GetMethodName(pf_.get(), methodId);
820        decoder.MatchAndMarkMethod(pf_.get(), targetRecordName, methodName, methodId);
821        ASSERT_TRUE(!decoder.Match(pf_.get(), targetRecordName, methodId));
822        auto callback = [methodName, &decoder, jsPandaFile = pf_](uint32_t offset, const PGOType *type) {
823            ASSERT_NE(offset, 0);
824            if (type->IsScalarOpType()) {
825                auto sampleType = *reinterpret_cast<const PGOSampleType *>(type);
826                if (sampleType.IsProfileType()) {
827                    ASSERT_EQ(std::string(methodName), "func_main_0");
828                    PGOHClassTreeDesc *desc;
829                    if (!decoder.GetHClassTreeDesc(sampleType, &desc)) {
830                        return;
831                    }
832                    return;
833                    auto classId = EntityId(sampleType.GetProfileType().GetId());
834                    auto className = MethodLiteral::GetMethodName(jsPandaFile.get(), classId);
835                    if (std::string(className) == "Arm") {
836                        auto superClassId = EntityId(desc->GetProfileType().GetId());
837                        auto superClassName = MethodLiteral::GetMethodName(jsPandaFile.get(), superClassId);
838                        ASSERT_EQ(std::string(superClassName), "Body");
839                    } else if (std::string(className) == "Foot") {
840                        auto superClassId = EntityId(desc->GetProfileType().GetId());
841                        auto superClassName = MethodLiteral::GetMethodName(jsPandaFile.get(), superClassId);
842                        ASSERT_EQ(std::string(superClassName), "Body");
843                    } else {
844                        ASSERT_EQ(desc->GetProfileType().GetRaw(), 0);
845                    }
846                }
847            }
848        };
849        decoder.GetTypeInfo(pf_.get(), targetRecordName, methodLiteral,
850                            callback);
851    }
852    unlink("ark-profiler15/modules.ap");
853    rmdir("ark-profiler15/");
854}
855
856HWTEST_F_L0(PGOProfilerTest, OpTypeTest)
857{
858    mkdir("ark-profiler16/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
859    const char *targetRecordName = "op_type_test";
860    ExecuteAndLoadJSPandaFile("ark-profiler16/", targetRecordName);
861    ASSERT_NE(pf_, nullptr);
862    uint32_t checksum = pf_->GetChecksum();
863
864    // Loader
865    PGOProfilerDecoder decoder("ark-profiler16/modules.ap", 1);
866    ASSERT_TRUE(decoder.LoadAndVerify(checksum));
867    std::string types[17] =
868        { "1", "5", "4", "4", "4", "4", "4", "4", "5", "4", "4", "1", "1", "4", "5", "1", "1" };
869    int index = 0;
870    auto methodLiterals = pf_->GetMethodLiteralMap();
871    for (auto iter : methodLiterals) {
872        auto methodLiteral = iter.second;
873        auto methodId = methodLiteral->GetMethodId();
874        auto methodName = methodLiteral->GetMethodName(pf_.get(), methodId);
875        if (std::string(methodName) != "sun" && std::string(methodName) != "sun1") {
876            decoder.MatchAndMarkMethod(pf_.get(), targetRecordName, methodName, methodId);
877            ASSERT_TRUE(!decoder.Match(pf_.get(), targetRecordName, methodId));
878        }
879        auto callback = [methodName, types, &index](uint32_t offset, const PGOType *type) {
880            ASSERT_NE(offset, 0);
881            if (type->IsScalarOpType()) {
882                auto sampleType = *reinterpret_cast<const PGOSampleType *>(type);
883                if (sampleType.IsProfileType()) {
884                    return;
885                }
886                if (std::string(methodName) == "advance") {
887                    if (sampleType.GetWeight() > 0) {
888                        auto trueWeight = sampleType.GetWeight() >> 10;
889                        auto falseWeight = sampleType.GetWeight() & 0x7FF;
890                        auto primitiveType = sampleType.GetPrimitiveType();
891                        ASSERT_GT(trueWeight, falseWeight);
892                        ASSERT_EQ(static_cast<uint32_t>(primitiveType), PGOSampleType::IntType());
893                    } else {
894                        ASSERT_EQ(sampleType.GetTypeString(), types[index++]);
895                    }
896                }
897            }
898        };
899        decoder.GetTypeInfo(pf_.get(), targetRecordName, methodLiteral,
900                            callback);
901    }
902    unlink("ark-profiler16/modules.ap");
903    rmdir("ark-profiler16/");
904}
905
906HWTEST_F_L0(PGOProfilerTest, ArrayProfileTest)
907{
908    mkdir("ark-profiler18/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
909    const char *targetRecordName = "array_test";
910    ExecuteAndLoadJSPandaFile("ark-profiler18/", targetRecordName);
911    ASSERT_NE(pf_, nullptr);
912    uint32_t checksum = pf_->GetChecksum();
913
914    // Loader
915    PGOProfilerDecoder decoder("ark-profiler18/modules.ap", 1);
916    ASSERT_TRUE(decoder.LoadAndVerify(checksum));
917    auto methodLiterals = pf_->GetMethodLiteralMap();
918    for (auto iter : methodLiterals) {
919        auto methodLiteral = iter.second;
920        auto methodId = methodLiteral->GetMethodId();
921        auto methodName = methodLiteral->GetMethodName(pf_.get(), methodId);
922        decoder.MatchAndMarkMethod(pf_.get(), targetRecordName, methodName, methodId);
923        ASSERT_TRUE(!decoder.Match(pf_.get(), targetRecordName, methodId));
924        auto callback = [methodName, &decoder, jsPandaFile = pf_](uint32_t offset, const PGOType *type) {
925            if (type->IsScalarOpType()) {
926                auto sampleType = *reinterpret_cast<const PGOSampleType *>(type);
927                if (sampleType.IsProfileType()) {
928                    ASSERT_EQ(std::string(methodName), "func_main_0");
929                    PGOHClassTreeDesc *desc;
930                    if (!decoder.GetHClassTreeDesc(sampleType, &desc)) {
931                        return;
932                    }
933                }
934            } else if (type->IsRwOpType()) {
935                auto pgoRWOpType = *reinterpret_cast<const PGORWOpType *>(type);
936                if (std::string(methodName) == "foo") {
937                    ASSERT_TRUE(pgoRWOpType.GetCount() == 3);
938                    auto classType = pgoRWOpType.GetObjectInfo(0).GetProfileType();
939                    ASSERT_TRUE(classType.IsBuiltinsArray());
940                    ASSERT_EQ(classType.GetElementsKindBeforeTransition(), ElementsKind::NUMBER);
941
942                    classType = pgoRWOpType.GetObjectInfo(1).GetProfileType();
943                    ASSERT_TRUE(classType.IsBuiltinsArray());
944                    ASSERT_EQ(classType.GetElementsKindBeforeTransition(), ElementsKind::HOLE_INT);
945
946                    classType = pgoRWOpType.GetObjectInfo(2).GetProfileType();
947                    ASSERT_TRUE(classType.IsBuiltinsArray());
948                    ASSERT_EQ(classType.GetElementsKindBeforeTransition(), ElementsKind::TAGGED);
949                } else if (std::string(methodName) == "foo1") {
950                    ASSERT_TRUE(pgoRWOpType.GetCount() == 2);
951                    auto classType = pgoRWOpType.GetObjectInfo(0).GetProfileType();
952                    ASSERT_TRUE(classType.IsBuiltinsArray());
953                    ASSERT_EQ(classType.GetElementsKindBeforeTransition(), ElementsKind::NUMBER);
954
955                    classType = pgoRWOpType.GetObjectInfo(1).GetProfileType();
956                    ASSERT_TRUE(classType.IsBuiltinsArray());
957                    ASSERT_EQ(classType.GetElementsKindBeforeTransition(), ElementsKind::TAGGED);
958                } else if (std::string(methodName) == "foo2") {
959                    ASSERT_TRUE(pgoRWOpType.GetCount() == 1);
960                    auto classType = pgoRWOpType.GetObjectInfo(0).GetProfileType();
961                    ASSERT_TRUE(classType.IsBuiltinsArray());
962                    ASSERT_EQ(classType.GetElementsKindBeforeTransition(), ElementsKind::HOLE_TAGGED);
963                }
964            }
965        };
966        decoder.GetTypeInfo(pf_.get(), targetRecordName, methodLiteral,
967                            callback);
968    }
969    unlink("ark-profiler18/modules.ap");
970    rmdir("ark-profiler18/");
971}
972
973HWTEST_F_L0(PGOProfilerTest, ObjectLiteralProfileTest)
974{
975    mkdir("ark-profiler20/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
976    const char *targetRecordName = "object_literal";
977    ExecuteAndLoadJSPandaFile("ark-profiler20/", targetRecordName);
978    ASSERT_NE(pf_, nullptr);
979    uint32_t checksum = pf_->GetChecksum();
980
981    // Loader
982    PGOProfilerDecoder decoder("ark-profiler20/modules.ap", 1);
983    ASSERT_TRUE(decoder.LoadAndVerify(checksum));
984    auto methodLiterals = pf_->GetMethodLiteralMap();
985    for (auto iter : methodLiterals) {
986        auto methodLiteral = iter.second;
987        auto methodId = methodLiteral->GetMethodId();
988        auto methodName = methodLiteral->GetMethodName(pf_.get(), methodId);
989        decoder.MatchAndMarkMethod(pf_.get(), targetRecordName, methodName, methodId);
990        ASSERT_TRUE(!decoder.Match(pf_.get(), targetRecordName, methodId));
991        auto callback = [methodName, &decoder, jsPandaFile = pf_](uint32_t offset, const PGOType *type) {
992            if (type->IsScalarOpType()) {
993                auto sampleType = *reinterpret_cast<const PGOSampleType *>(type);
994                if (sampleType.IsProfileType()) {
995                    ASSERT_EQ(std::string(methodName), "func_main_0");
996                    PGOHClassTreeDesc *desc;
997                    if (!decoder.GetHClassTreeDesc(sampleType, &desc)) {
998                        return;
999                    }
1000                }
1001            } else if (type->IsRwOpType()) {
1002                auto pgoRWOpType = *reinterpret_cast<const PGORWOpType *>(type);
1003                if (std::string(methodName) == "foo") {
1004                    ASSERT_TRUE(pgoRWOpType.GetCount() == 2);
1005                    auto classType = PGOSampleType(pgoRWOpType.GetObjectInfo(0).GetProfileType());
1006                    PGOHClassTreeDesc *desc;
1007                    ASSERT_TRUE(decoder.GetHClassTreeDesc(classType, &desc));
1008
1009                    classType = PGOSampleType(pgoRWOpType.GetObjectInfo(1).GetProfileType());
1010                    ASSERT_TRUE(decoder.GetHClassTreeDesc(classType, &desc));
1011                }
1012            }
1013        };
1014        decoder.GetTypeInfo(pf_.get(), targetRecordName, methodLiteral,
1015                            callback);
1016    }
1017    unlink("ark-profiler20/modules.ap");
1018    rmdir("ark-profiler20/");
1019}
1020
1021HWTEST_F_L0(PGOProfilerTest, ArraySizeProfileTest)
1022{
1023    mkdir("ark-profiler21/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
1024    const char *targetRecordName = "array_size_test";
1025    ExecuteAndLoadJSPandaFile("ark-profiler21/", targetRecordName);
1026    ASSERT_NE(pf_, nullptr);
1027    uint32_t checksum = pf_->GetChecksum();
1028
1029    // Loader
1030    PGOProfilerDecoder decoder("ark-profiler21/modules.ap", 1);
1031    ASSERT_TRUE(decoder.LoadAndVerify(checksum));
1032    auto methodLiterals = pf_->GetMethodLiteralMap();
1033    for (auto iter : methodLiterals) {
1034        auto methodLiteral = iter.second;
1035        auto methodId = methodLiteral->GetMethodId();
1036        auto methodName = methodLiteral->GetMethodName(pf_.get(), methodId);
1037        decoder.MatchAndMarkMethod(pf_.get(), targetRecordName, methodName, methodId);
1038        ASSERT_TRUE(!decoder.Match(pf_.get(), targetRecordName, methodId));
1039        auto callback = [methodName, jsPandaFile = pf_](uint32_t offset, const PGOType *type) {
1040            if (type->IsDefineOpType()) {
1041                auto defineOptype = reinterpret_cast<const PGODefineOpType *>(type);
1042                    if (std::string(methodName) == "foo") {
1043                        ASSERT_EQ(defineOptype->GetElementsLength(), 4);
1044                    } else if (std::string(methodName) == "foo1") {
1045                        ASSERT_EQ(defineOptype->GetElementsLength(), 12);
1046                    } else if (std::string(methodName) == "foo2") {
1047                        ASSERT_EQ(defineOptype->GetElementsLength(), 12);
1048                    }
1049            }
1050        };
1051        decoder.GetTypeInfo(pf_.get(), targetRecordName, methodLiteral,
1052                            callback);
1053    }
1054    unlink("ark-profiler21/modules.ap");
1055    rmdir("ark-profiler21/");
1056}
1057
1058HWTEST_F_L0(PGOProfilerTest, StringEqualProfileTest)
1059{
1060    mkdir("ark-profiler22/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
1061    const char *targetRecordName = "string_equal";
1062    ExecuteAndLoadJSPandaFile("ark-profiler22/", targetRecordName);
1063    ASSERT_NE(pf_, nullptr);
1064    uint32_t checksum = pf_->GetChecksum();
1065
1066    // Loader
1067    PGOProfilerDecoder decoder("ark-profiler22/modules.ap", 1);
1068    ASSERT_TRUE(decoder.LoadAndVerify(checksum));
1069    auto methodLiterals = pf_->GetMethodLiteralMap();
1070    for (auto iter : methodLiterals) {
1071        auto methodLiteral = iter.second;
1072        auto methodId = methodLiteral->GetMethodId();
1073        auto methodName = methodLiteral->GetMethodName(pf_.get(), methodId);
1074        decoder.MatchAndMarkMethod(pf_.get(), targetRecordName, methodName, methodId);
1075        ASSERT_TRUE(!decoder.Match(pf_.get(), targetRecordName, methodId));
1076        auto callback = [methodName, jsPandaFile = pf_](uint32_t offset, const PGOType *type) {
1077            if (type->IsScalarOpType()) {
1078                auto sampleType = *reinterpret_cast<const PGOSampleType *>(type);
1079                if (sampleType.IsProfileType()) {
1080                    return;
1081                }
1082                if (std::string(methodName) == "foo1" ||
1083                    std::string(methodName) == "foo2") {
1084                    auto primitiveType = sampleType.GetPrimitiveType();
1085                    ASSERT_EQ(static_cast<uint32_t>(primitiveType), PGOSampleType::StringType());
1086                }
1087            }
1088        };
1089        decoder.GetTypeInfo(pf_.get(), targetRecordName, methodLiteral,
1090                            callback);
1091    }
1092    unlink("ark-profiler22/modules.ap");
1093    rmdir("ark-profiler22/");
1094}
1095
1096HWTEST_F_L0(PGOProfilerTest, BuiltinsTest)
1097{
1098    mkdir("ark-profiler23/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
1099    const char *targetRecordName = "builtins_test";
1100    ExecuteAndLoadJSPandaFile("ark-profiler23/", targetRecordName);
1101    ASSERT_NE(pf_, nullptr);
1102    uint32_t checksum = pf_->GetChecksum();
1103
1104    // Loader
1105    PGOProfilerDecoder decoder("ark-profiler23/modules.ap", 1);
1106    ASSERT_TRUE(decoder.LoadAndVerify(checksum));
1107    auto methodLiterals = pf_->GetMethodLiteralMap();
1108    for (auto iter : methodLiterals) {
1109        auto methodLiteral = iter.second;
1110        auto methodId = methodLiteral->GetMethodId();
1111        auto methodName = methodLiteral->GetMethodName(pf_.get(), methodId);
1112        if (std::string(methodName) != "ArrayList") {
1113            decoder.MatchAndMarkMethod(pf_.get(), targetRecordName, methodName, methodId);
1114            ASSERT_TRUE(!decoder.Match(pf_.get(), targetRecordName, methodId));
1115        }
1116        auto callback = [methodName](uint32_t offset, const PGOType *type) {
1117            ASSERT_NE(offset, 0);
1118            if (type->IsRwOpType() && std::string(methodName) == "A") {
1119                auto pgoRWOpType = *reinterpret_cast<const PGORWOpType *>(type);
1120                ASSERT_TRUE(pgoRWOpType.GetCount() == 1);
1121            }
1122        };
1123        decoder.GetTypeInfo(pf_.get(), targetRecordName, methodLiteral,
1124                            callback);
1125    }
1126    unlink("ark-profiler23/modules.ap");
1127    rmdir("ark-profiler23/");
1128}
1129
1130#endif
1131
1132#if defined(SUPPORT_ENABLE_ASM_INTERP)
1133HWTEST_F_L0(PGOProfilerTest, FileConsistencyCheck)
1134{
1135    mkdir("ark-profiler17/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
1136    const char *targetRecordName = "sample_test";
1137    ExecuteAndLoadJSPandaFile("ark-profiler17/", targetRecordName);
1138    ASSERT_NE(pf_, nullptr);
1139    uint32_t checksum = pf_->GetChecksum();
1140
1141    // write to corrupt the ap file's consistency
1142    std::ofstream fWriter("ark-profiler17/modules.ap", std::fstream::app);
1143
1144    fWriter.write(reinterpret_cast<char *>(&checksum), sizeof(checksum));
1145    fWriter.seekp(100);
1146    fWriter.write(reinterpret_cast<char *>(&checksum), sizeof(checksum));
1147    fWriter.close();
1148
1149    // Loader
1150    PGOProfilerDecoder loader("ark-profiler17/modules.ap", DECODER_THRESHOLD);
1151    ASSERT_FALSE(loader.LoadAndVerify(checksum));
1152    unlink("ark-profiler17/modules.ap");
1153    rmdir("ark-profiler17/");
1154}
1155
1156HWTEST_F_L0(PGOProfilerTest, MergeApSelfTwice)
1157{
1158    mkdir("ark-profiler18/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
1159    const char *targetRecordName = "op_type_test";
1160    ExecuteAndLoadJSPandaFile("ark-profiler18/", targetRecordName);
1161    ASSERT_NE(pf_, nullptr);
1162
1163    // Loader
1164    PGOProfilerDecoder decoder("ark-profiler18/modules_merge.ap", 1);
1165    PGOProfilerDecoder decoderSingle("ark-profiler18/modules.ap", 1);
1166    ASSERT_TRUE(PGOProfilerManager::MergeApFiles("ark-profiler18/modules.ap:ark-profiler18/modules.ap",
1167                                                 "ark-profiler18/modules_merge.ap", 1, ApGenMode::OVERWRITE));
1168    ASSERT_TRUE(decoder.LoadFull());
1169    ASSERT_TRUE(decoderSingle.LoadFull());
1170
1171    auto doubleCount =
1172        decoder.GetRecordDetailInfos().GetRecordInfos().begin()->second->GetMethodInfos().begin()->second->GetCount();
1173    auto singleCount = decoderSingle.GetRecordDetailInfos()
1174                            .GetRecordInfos()
1175                            .begin()
1176                            ->second->GetMethodInfos()
1177                            .begin()
1178                            ->second->GetCount();
1179    ASSERT_EQ(doubleCount, singleCount + singleCount);
1180
1181    unlink("ark-profiler18/modules.ap");
1182    unlink("ark-profiler18/modules_merge.ap");
1183    rmdir("ark-profiler18/");
1184}
1185#endif
1186
1187HWTEST_F_L0(PGOProfilerTest, RuntimeMerge)
1188{
1189    mkdir("ark-profiler19/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
1190    ExecuteAndLoadJSPandaFile("ark-profiler19/", "truck");
1191    ExecuteAndLoadJSPandaFile("ark-profiler19/", "call_test");
1192    ExecuteAndLoadJSPandaFile("ark-profiler19/", "truck");
1193
1194    // Loader
1195    PGOProfilerDecoder loader("ark-profiler19/modules.ap", DECODER_THRESHOLD);
1196    CString expectRecordName = "sample_test";
1197#if defined(SUPPORT_ENABLE_ASM_INTERP)
1198    std::unordered_map<std::string, std::unordered_map<std::string, std::vector<PGOMethodId>>> methodIdInAp;
1199    ParseRelatedPandaFileMethods(loader, methodIdInAp);
1200    ASSERT_EQ(methodIdInAp.size(), 3);
1201    CheckApMethods(methodIdInAp);
1202#else
1203    uint32_t checksum = pf_->GetChecksum();
1204    ASSERT_TRUE(!loader.LoadAndVerify(checksum));
1205#endif
1206    unlink("ark-profiler19/modules.ap");
1207    rmdir("ark-profiler19/");
1208}
1209
1210HWTEST_F_L0(PGOProfilerTest, ProfdumpMerge)
1211{
1212    mkdir("ark-profiler20/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
1213
1214    ExecuteAndLoadJSPandaFile("ark-profiler20/merge_file_1.ap", "merge_file_1");
1215    ExecuteAndLoadJSPandaFile("ark-profiler20/merge_file_2.ap", "merge_file_2");
1216    ExecuteAndLoadJSPandaFile("ark-profiler20/merge_file_3.ap", "merge_file_3");
1217
1218    // Loader
1219    PGOProfilerDecoder loader("ark-profiler20/merged.ap", DECODER_THRESHOLD);
1220    ASSERT_TRUE(PGOProfilerManager::MergeApFiles(
1221        "ark-profiler20/merge_file_1.ap:ark-profiler20/merge_file_2.ap:ark-profiler20/merge_file_3.ap",
1222        "ark-profiler20/merged.ap", 1, ApGenMode::OVERWRITE));
1223
1224    CString expectRecordName = "sample_test";
1225#if defined(SUPPORT_ENABLE_ASM_INTERP)
1226    std::unordered_map<std::string, std::unordered_map<std::string, std::vector<PGOMethodId>>> methodIdInAp;
1227    ParseRelatedPandaFileMethods(loader, methodIdInAp);
1228    ASSERT_EQ(methodIdInAp.size(), 3);
1229    CheckApMethods(methodIdInAp);
1230#else
1231    uint32_t checksum = pf_->GetChecksum();
1232    ASSERT_TRUE(!loader.LoadAndVerify(checksum));
1233#endif
1234    unlink("ark-profiler20/merge_file_1.ap");
1235    unlink("ark-profiler20/merge_file_2.ap");
1236    unlink("ark-profiler20/merge_file_3.ap");
1237    unlink("ark-profiler20/merged.ap");
1238    rmdir("ark-profiler20/");
1239}
1240
1241HWTEST_F_L0(PGOProfilerTest, ApVersionMatchCheck)
1242{
1243    mkdir("ark-ApVersionMatchCheck/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
1244    const char *targetRecordName = "sample_test";
1245    ExecuteAndLoadJSPandaFile("ark-ApVersionMatchCheck/", targetRecordName);
1246    ASSERT_NE(pf_, nullptr);
1247
1248    PGOProfilerEncoderMock encoder("ark-ApVersionMatchCheck/modules.ap", DECODER_THRESHOLD,
1249                                   PGOProfilerEncoder::ApGenMode::MERGE);
1250    encoder.InitializeData();
1251    encoder.SetVersion(PGOProfilerHeader::PROFILE_TYPE_WITH_ABC_ID_MINI_VERSION);
1252    encoder.Save();
1253
1254    PGOProfilerDecoder decoder("ark-ApVersionMatchCheck/modules.ap", DECODER_THRESHOLD);
1255    PGOProfilerHeader::SetStrictMatch(true);
1256    ASSERT_FALSE(decoder.LoadFull());
1257    PGOProfilerHeader::SetStrictMatch(false);
1258    ASSERT_TRUE(decoder.LoadFull());
1259
1260    unlink("ark-ApVersionMatchCheck/modules.ap");
1261    unlink("ark-ApVersionMatchCheck/");
1262}
1263
1264HWTEST_F_L0(PGOProfilerTest, TypedArrayOnHeap)
1265{
1266    mkdir("ark-profiler24/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
1267    const char *targetRecordName = "typedarray_length";
1268    ExecuteAndLoadJSPandaFile("ark-profiler24/", targetRecordName);
1269    ASSERT_NE(pf_, nullptr);
1270    uint32_t checksum = pf_->GetChecksum();
1271
1272    // Loader
1273    PGOProfilerDecoder decoder("ark-profiler24/modules.ap", 1);
1274    ASSERT_TRUE(decoder.LoadAndVerify(checksum));
1275    auto methodLiterals = pf_->GetMethodLiteralMap();
1276    for (auto iter : methodLiterals) {
1277        auto methodLiteral = iter.second;
1278        auto methodId = methodLiteral->GetMethodId();
1279        auto methodName = methodLiteral->GetMethodName(pf_.get(), methodId);
1280        auto callback = [methodName](uint32_t offset, const PGOType *type) {
1281            ASSERT_NE(offset, 0);
1282            if (type->IsRwOpType() && std::string(methodName) == "test") {
1283                auto pgoRWOpType = *reinterpret_cast<const PGORWOpType *>(type);
1284                ASSERT_TRUE(pgoRWOpType.GetCount() == 1);
1285            }
1286        };
1287        decoder.GetTypeInfo(pf_.get(), targetRecordName, methodLiteral,
1288                            callback);
1289    }
1290    unlink("ark-profiler24/modules.ap");
1291    rmdir("ark-profiler24/");
1292}
1293
1294HWTEST_F_L0(PGOProfilerTest, ProfileTypeConstructor)
1295{
1296    mkdir("ark-profiler25/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
1297    const char *targetRecordName = "typedarray_length";
1298    ExecuteAndLoadJSPandaFile("ark-profiler25/", targetRecordName);
1299    ASSERT_NE(pf_, nullptr);
1300    ApEntityId inValidId = 555;
1301    ApEntityId validId = 64;
1302    // Loader
1303    PGOProfilerDecoder decoder("ark-profiler25/modules.ap", 1);
1304    ASSERT_TRUE(decoder.LoadFull());
1305
1306    auto invalidRes = ProfileTypeRef(inValidId);
1307    auto expectFalse = ProfileType::CreateFromProfileTypeRef(decoder.GetRecordDetailInfos(), invalidRes);
1308    EXPECT_FALSE(expectFalse.has_value());
1309
1310    auto validRes = ProfileTypeRef(validId);
1311    auto expectTrue = ProfileType::CreateFromProfileTypeRef(decoder.GetRecordDetailInfos(), validRes);
1312    EXPECT_TRUE(expectTrue.has_value());
1313    unlink("ark-profiler25/modules.ap");
1314    rmdir("ark-profiler25/");
1315}
1316
1317HWTEST_F_L0(PGOProfilerTest, CompatibleWithAOTFileTest)
1318{
1319    constexpr uint32_t CHECKSUM = 1;
1320    PGOProfilerDecoder decoder("", DECODER_THRESHOLD);
1321    EXPECT_TRUE(decoder.LoadAndVerify(CHECKSUM));
1322    EXPECT_FALSE(decoder.IsCompatibleWithAOTFile());
1323}
1324
1325HWTEST_F_L0(PGOProfilerTest, ExternalMethodLiteralTest)
1326{
1327    mkdir("ark-profiler26/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
1328    const char *targetRecordName = "typedarray_length";
1329    ExecuteAndLoadJSPandaFile("ark-profiler26/", targetRecordName);
1330    ASSERT_NE(pf_, nullptr);
1331    uint32_t checksum = pf_->GetChecksum();
1332
1333    PGOProfilerDecoder decoder("ark-profiler26/modules.ap", DECODER_THRESHOLD);
1334    ASSERT_TRUE(decoder.LoadAndVerify(checksum));
1335    auto callback = []([[maybe_unused]] uint32_t offset, [[maybe_unused]] const PGOType *type) {
1336        EXPECT_TRUE(false);
1337    };
1338    decoder.GetTypeInfo(pf_.get(), targetRecordName, nullptr,
1339                        callback);
1340    unlink("ark-profiler26/modules.ap");
1341    rmdir("ark-profiler26/");
1342}
1343
1344HWTEST_F_L0(PGOProfilerTest, PGOObjectInfoOperatorLessThanTest)
1345{
1346    constexpr uint64_t rawTypeLess = 0;
1347    constexpr uint64_t rawTypeGreater = 1;
1348
1349    ProfileType profileTypeLess(rawTypeLess);
1350    ProfileType profileTypeGreater(rawTypeGreater);
1351
1352    PGOObjectInfo objectInfoLess(profileTypeLess, profileTypeGreater, profileTypeGreater,
1353                                 profileTypeGreater, profileTypeGreater, profileTypeGreater, PGOSampleType());
1354    PGOObjectInfo objectInfoGreater(profileTypeGreater, profileTypeLess, profileTypeGreater,
1355                                    profileTypeGreater, profileTypeGreater, profileTypeGreater, PGOSampleType());
1356
1357    EXPECT_TRUE(objectInfoLess < objectInfoGreater);
1358    EXPECT_FALSE(objectInfoGreater < objectInfoLess);
1359}
1360
1361HWTEST_F_L0(PGOProfilerTest, PGODisableWithAOTFileWorkloadTest)
1362{
1363    mkdir("ark-profiler27/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
1364    std::ofstream fWriter("ark-profiler27/tmp.an", std::fstream::app);
1365    fWriter.close();
1366    const char *targetRecordName = "typedarray_length";
1367    std::string targetAbcPath = std::string(TARGET_ABC_PATH) + targetRecordName + ".abc";
1368    // Force set in advance to simulate AOT/JIT enable list check is passed in UT
1369    ecmascript::AnFileDataManager::GetInstance()->SetEnable(true);
1370    ecmascript::AnFileDataManager::GetInstance()->SetDir("ark-profiler27/tmp");
1371    RuntimeOption option;
1372    option.SetEnableProfile(true);
1373    option.SetProfileDir("ark-profiler27/");
1374    EcmaVM *ecmaVM = JSNApi::CreateJSVM(option);
1375    JSNApi::LoadAotFile(ecmaVM, "");
1376    EXPECT_TRUE(ecmaVM->IsEnablePGOProfiler());
1377    auto result = JSNApi::Execute(ecmaVM, targetAbcPath, targetRecordName, false);
1378    EXPECT_TRUE(result);
1379    JSNApi::DestroyJSVM(ecmaVM);
1380    EXPECT_TRUE(FileExist("ark-profiler27/modules.ap"));
1381    unlink("ark-profiler27/modules.ap");
1382    unlink("ark-profiler27/tmp.an");
1383    rmdir("ark-profiler27/");
1384}
1385
1386HWTEST_F_L0(PGOProfilerTest, PGODisableWithAOTFileAppTest)
1387{
1388    mkdir("ark-profiler27/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
1389    std::ofstream fWriter("ark-profiler27/tmp.an", std::fstream::app);
1390    fWriter.close();
1391    const char *targetRecordName = "typedarray_length";
1392    std::string targetAbcPath = std::string(TARGET_ABC_PATH) + targetRecordName + ".abc";
1393    // Force set in advance to simulate AOT/JIT enable list check is passed in UT
1394    ecmascript::AnFileDataManager::GetInstance()->SetEnable(true);
1395    ecmascript::AnFileDataManager::GetInstance()->SetDir("ark-profiler27/tmp");
1396    RuntimeOption option;
1397    EcmaVM *ecmaVM = JSNApi::CreateJSVM(option);
1398    option.SetEnableProfile(true);
1399    option.SetProfileDir("ark-profiler27/");
1400    JSNApi::PreFork(ecmaVM);
1401    JSNApi::PostFork(ecmaVM, option);
1402    EXPECT_TRUE(ecmaVM->IsEnablePGOProfiler());
1403    JSNApi::LoadAotFile(ecmaVM, "");
1404    EXPECT_FALSE(ecmaVM->IsEnablePGOProfiler());
1405    auto result = JSNApi::Execute(ecmaVM, targetAbcPath, targetRecordName, false);
1406    EXPECT_TRUE(result);
1407    JSNApi::DestroyJSVM(ecmaVM);
1408    EXPECT_FALSE(FileExist("ark-profiler27/modules.ap"));
1409    unlink("ark-profiler27/tmp.an");
1410    rmdir("ark-profiler27/");
1411}
1412
1413HWTEST_F_L0(PGOProfilerTest, PGODisableUnderAOTFailTest)
1414{
1415    std::map<std::string, int32_t> mockAOTCompileStatusMap;
1416    mockAOTCompileStatusMap["module1"] = 0;
1417    mockAOTCompileStatusMap["module2"] = 1;
1418    mockAOTCompileStatusMap["module3"] = 4;
1419    RuntimeOption option;
1420    {
1421        // Not update existing setting when AOT compilation uninitialized or succeed
1422        EcmaVM *ecmaVM = JSNApi::CreateJSVM(option);
1423        RuntimeOption localOption = option;
1424        localOption.SetEnableProfile(true);
1425        localOption.SetAOTCompileStatusMap(mockAOTCompileStatusMap);
1426        JSNApi::PreFork(ecmaVM);
1427        JSNApi::PostFork(ecmaVM, localOption);
1428        EXPECT_FALSE(ecmaVM->GetJSOptions().GetAOTHasException());
1429        JSNApi::DestroyJSVM(ecmaVM);
1430    }
1431    {
1432        // Disable existing setting when AOT compilation failed
1433        EcmaVM *ecmaVM = JSNApi::CreateJSVM(option);
1434        RuntimeOption localOption = option;
1435        mockAOTCompileStatusMap["module4"] = 2;
1436        localOption.SetAOTCompileStatusMap(mockAOTCompileStatusMap);
1437        JSNApi::PreFork(ecmaVM);
1438        JSNApi::PostFork(ecmaVM, localOption);
1439        EXPECT_TRUE(ecmaVM->GetJSOptions().GetAOTHasException());
1440        JSNApi::DestroyJSVM(ecmaVM);
1441    }
1442    {
1443        // Disable existing setting when AOT compilation crashed
1444        EcmaVM *ecmaVM = JSNApi::CreateJSVM(option);
1445        RuntimeOption localOption = option;
1446        mockAOTCompileStatusMap["module4"] = 3;
1447        localOption.SetAOTCompileStatusMap(mockAOTCompileStatusMap);
1448        JSNApi::PreFork(ecmaVM);
1449        JSNApi::PostFork(ecmaVM, localOption);
1450        EXPECT_TRUE(ecmaVM->GetJSOptions().GetAOTHasException());
1451        JSNApi::DestroyJSVM(ecmaVM);
1452    }
1453}
1454
1455HWTEST_F_L0(PGOProfilerTest, EnableForceICTest)
1456{
1457    RuntimeOption option;
1458    EcmaVM* ecmaVM = JSNApi::CreateJSVM(option);
1459    JSThread* jsThread = ecmaVM->GetJSThread();
1460    JSRuntimeOptions& jsOption = ecmaVM->GetJSOptions();
1461    EXPECT_TRUE(jsThread->IsEnableForceIC());
1462    EXPECT_TRUE(jsOption.IsEnableForceIC());
1463    EXPECT_TRUE(ecmascript::pgo::PGOProfilerManager::GetInstance()->IsEnableForceIC());
1464
1465    JSNApi::PreFork(ecmaVM);
1466    JSNApi::PostFork(ecmaVM, option);
1467    EXPECT_FALSE(jsThread->IsEnableForceIC());
1468    EXPECT_FALSE(jsOption.IsEnableForceIC());
1469    EXPECT_FALSE(ecmascript::pgo::PGOProfilerManager::GetInstance()->IsEnableForceIC());
1470
1471    JSNApi::DestroyJSVM(ecmaVM);
1472}
1473}  // namespace panda::test
1474