• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024-2025 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 "gtest/gtest.h"
17 
18 #include "ecmascript/compiler/aot_compilation_env.h"
19 #include "ecmascript/compiler/aot_compiler_preprocessor.h"
20 #include "ecmascript/compiler/aot_compiler_stats.h"
21 #include "ecmascript/compiler/aot_file/an_file_data_manager.h"
22 #include "ecmascript/compiler/aot_file/tests/aot_file_generator_mock.h"
23 #include "ecmascript/compiler/pass_manager.h"
24 #include "ecmascript/compiler/pass_options.h"
25 #include "ecmascript/js_runtime_options.h"
26 #include "ecmascript/ohos/ohos_pkg_args.h"
27 #include "ecmascript/platform/filesystem.h"
28 #include "ecmascript/tests/test_helper.h"
29 
30 using namespace panda;
31 using namespace panda::ecmascript;
32 using namespace panda::ecmascript::kungfu;
33 using namespace panda::ecmascript::pgo;
34 using namespace panda::panda_file;
35 using namespace panda::ecmascript::filesystem;
36 
37 namespace panda::test {
38 class AOTFileTest : public testing::Test {
39 public:
SetUpTestCase()40     static void SetUpTestCase()
41     {
42         GTEST_LOG_(INFO) << "SetUpTestCase";
43     }
44 
TearDownTestCase()45     static void TearDownTestCase()
46     {
47         GTEST_LOG_(INFO) << "TearDownTestCase";
48     }
49 
SetUp()50     void SetUp() override
51     {
52         this->testDir_ = std::string(TARGET_ABC_PATH);
53     }
54 
TearDown()55     void TearDown() override
56     {
57         if (Exists(this->testAnPath_.c_str())) {
58             Unlink(this->testAnPath_.c_str());
59         }
60         if (Exists(this->testApPath_.c_str())) {
61             Unlink(this->testApPath_.c_str());
62         }
63         if (Exists(this->testAiPath_.c_str())) {
64             Unlink(this->testAiPath_.c_str());
65         }
66         if (Exists(this->workerAnPath_.c_str())) {
67             Unlink(this->workerAnPath_.c_str());
68         }
69         if (Exists(this->workerApPath_.c_str())) {
70             Unlink(this->workerApPath_.c_str());
71         }
72         if (Exists(this->workerAiPath_.c_str())) {
73             Unlink(this->workerAiPath_.c_str());
74         }
75         this->testDir_.clear();
76         this->testAbcPath_.clear();
77         this->testRecordName_.clear();
78         this->testApPath_.clear();
79         this->testAnPath_.clear();
80         this->testAiPath_.clear();
81         this->testAotPath_.clear();
82         this->workerAbcPath_.clear();
83         this->workerRecordName_.clear();
84         this->workerApPath_.clear();
85         this->workerAnPath_.clear();
86         this->workerAiPath_.clear();
87         this->workerAotPath_.clear();
88         this->testAnExpectedSize_ = 0;
89     }
90 
91 protected:
SetTestAbcPath(const std::string & abcFile)92     void SetTestAbcPath(const std::string &abcFile)
93     {
94         testAbcPath_ = testDir_ + abcFile;
95         ASSERT_TRUE(Exists(testAbcPath_));
96     }
97 
SetApPath()98     void SetApPath()
99     {
100         testApPath_ = testDir_ + testRecordName_ + ".ap";
101     }
102 
SetAotPath()103     void SetAotPath()
104     {
105         testAotPath_ = testDir_ + testRecordName_;
106     }
107 
SetAnPath()108     void SetAnPath()
109     {
110         testAnPath_ = testDir_ + testRecordName_ + ".an";
111     }
112 
SetAiPath()113     void SetAiPath()
114     {
115         testAiPath_ = testDir_ + testRecordName_ + ".ai";
116     }
117 
SetRecordName(const std::string & abcFile)118     void SetRecordName(const std::string &abcFile)
119     {
120         testRecordName_ = abcFile.substr(0, abcFile.find_last_of("."));
121         ASSERT_TRUE(!testRecordName_.empty());
122     }
123 
SetEnvrionmentForTest(const std::string & abcFile)124     void SetEnvrionmentForTest(const std::string &abcFile)
125     {
126         SetTestAbcPath(abcFile);
127         SetRecordName(abcFile);
128         SetApPath();
129         SetAotPath();
130         SetAnPath();
131         SetAiPath();
132     }
133 
SetWorkerAbcPath(const std::string & abcFile)134     void SetWorkerAbcPath(const std::string &abcFile)
135     {
136         workerAbcPath_ = testDir_ + abcFile;
137         ASSERT_TRUE(Exists(workerAbcPath_));
138     }
139 
SetWorkerApPath()140     void SetWorkerApPath()
141     {
142         workerApPath_ = testDir_ + workerRecordName_ + ".ap";
143     }
144 
SetWorkerAotPath()145     void SetWorkerAotPath()
146     {
147         workerAotPath_ = testDir_ + workerRecordName_;
148     }
149 
SetWorkerAnPath()150     void SetWorkerAnPath()
151     {
152         workerAnPath_ = testDir_ + workerRecordName_ + ".an";
153     }
154 
SetWorkerAiPath()155     void SetWorkerAiPath()
156     {
157         workerAiPath_ = testDir_ + workerRecordName_ + ".ai";
158     }
159 
SetWorkerRecordName(const std::string & abcFile)160     void SetWorkerRecordName(const std::string &abcFile)
161     {
162         workerRecordName_ = abcFile.substr(0, abcFile.find_last_of("."));
163         ASSERT_TRUE(!workerRecordName_.empty());
164     }
165 
SetEnvrionmentForWorker(const std::string & abcFile)166     void SetEnvrionmentForWorker(const std::string &abcFile)
167     {
168         SetWorkerAbcPath(abcFile);
169         SetWorkerRecordName(abcFile);
170         SetWorkerApPath();
171         SetWorkerAotPath();
172         SetWorkerAnPath();
173         SetWorkerAiPath();
174     }
175 
176     // Get .ap pgo profile for provided abc file
GetApFileInTest(std::string testApPath,std::string testRecordName,std::string testAbcPath)177     void GetApFileInTest(std::string testApPath, std::string testRecordName, std::string testAbcPath)
178     {
179         JSRuntimeOptions runtimeOptions;
180         runtimeOptions.SetEnablePGOProfiler(true);
181         runtimeOptions.SetPGOProfilerPath(testApPath);
182         runtimeOptions.SetEntryPoint(testRecordName);
183         EcmaVM *vm = JSNApi::CreateEcmaVM(runtimeOptions);
184         ASSERT_TRUE(vm != nullptr);
185         bool isMergeAbc = runtimeOptions.GetMergeAbc();
186         JSNApi::SetBundle(vm, !isMergeAbc);
187         bool res = JSNApi::Execute(vm, testAbcPath, runtimeOptions.GetEntryPoint());
188         ASSERT_TRUE(res);
189         JSNApi::DestroyJSVM(vm);
190         ASSERT_TRUE(Exists(testApPath));
191     }
192 
GetAnFileInTest(std::string testApPath,std::string testAotPath,std::string testAbcPath,size_t limitSizeByte=0)193     void GetAnFileInTest(std::string testApPath, std::string testAotPath, std::string testAbcPath,
194                          size_t limitSizeByte = 0)
195     {
196         bool ret = true;
197         JSRuntimeOptions runtimeOptions;
198         runtimeOptions.SetPGOProfilerPath(testApPath);
199         runtimeOptions.SetAOTOutputFile(testAotPath);
200         runtimeOptions.SetEnableAsmInterpreter(false);
201         runtimeOptions.SetOptionsForTargetCompilation();
202         ecmascript::AnFileDataManager::GetInstance()->SetEnable(true);
203         EcmaVM *vm = JSNApi::CreateEcmaVM(runtimeOptions);
204 
205         ASSERT_TRUE(vm != nullptr);
206         {
207             AOTCompilationEnv aotCompilationEnv(vm);
208             ecmascript::ThreadManagedScope managedScope(vm->GetJSThread());
209             LocalScope scope(vm);
210             arg_list_t pandaFileNames {testAbcPath};
211             std::map<std::string, std::shared_ptr<OhosPkgArgs>> pkgArgsMap;
212             CompilationOptions cOptions(runtimeOptions);
213             CompilerLog log(cOptions.logOption_);
214             AotMethodLogList logList(cOptions.logMethodsList_);
215             PGOProfilerDecoder profilerDecoder;
216             AotCompilerPreprocessor cPreprocessor(vm, runtimeOptions, pkgArgsMap, profilerDecoder, pandaFileNames);
217             AotCompilerStats compilerStats;
218             compilerStats.SetAotFilePath(cOptions.outputFileName_);
219             compilerStats.SetPgoPath(cOptions.profilerIn_);
220             compilerStats.StartCompiler();
221             profilerDecoder.SetHotnessThreshold(cOptions.hotnessThreshold_);
222             profilerDecoder.SetInPath(cOptions.profilerIn_);
223             cPreprocessor.AOTInitialize();
224             std::unordered_map<CString, uint32_t> originFilenameToChecksumMap;
225             cPreprocessor.GenerateAbcFileInfos(originFilenameToChecksumMap);
226             ret = cPreprocessor.GetCompilerResult();
227             cPreprocessor.HandleMergedPgoFile(originFilenameToChecksumMap);
228             cPreprocessor.Process(cOptions);
229             PassOptions::Builder optionsBuilder;
230             PassOptions passOptions = optionsBuilder.Build();
231             PassManager passManager(&aotCompilationEnv, cOptions.triple_, cOptions.optLevel_, cOptions.relocMode_, &log,
232                                     &logList, cOptions.maxAotMethodSize_, cOptions.maxMethodsInModule_, profilerDecoder,
233                                     &passOptions, cPreprocessor.GetCallMethodFlagMap(), cPreprocessor.GetAbcFileInfo(),
234                                     cPreprocessor.GetBcInfoCollectors(), cOptions.optBCRange_);
235             AOTFileGeneratorMock generator(&log, &logList, &aotCompilationEnv, cOptions.triple_, false, limitSizeByte);
236             passManager.CompileValidFiles(generator, ret, compilerStats);
237             if (generator.SaveAndGetAOTFileSize(cOptions.outputFileName_ + AOTFileManager::FILE_EXTENSION_AN, "",
238                                                 testAnExpectedSize_, originFilenameToChecksumMap)) {
239                 generator.SaveSnapshotFile();
240             }
241         }
242         JSNApi::DestroyJSVM(vm);
243         GTEST_LOG_(INFO) << "testAnPath_: " << testAnPath_;
244     }
245 
LoadAiInMultiThreadTest()246     void LoadAiInMultiThreadTest()
247     {
248         JSRuntimeOptions runtimeOptions;
249         runtimeOptions.SetEntryPoint(testRecordName_);
250         EcmaVM *vm = JSNApi::CreateEcmaVM(runtimeOptions);
251         std::string moduleName = "file_size_test";
252         std::string anFileName = "file_size_test.an";
253         std::string workerModuleName = "file_size_worker";
254         std::string workerAnFileName = "file_size_worker.an";
255         // init aot env
256         ecmascript::AnFileDataManager::GetInstance()->SetDir(testDir_);
257         ecmascript::AnFileDataManager::GetInstance()->SetEnable(true);
258         {
259             // simulate the case load aot file in main thread for entry-hap
260             vm->SetModuleName(moduleName.c_str());
261             JSNApi::LoadAotFile(vm, moduleName);
262             uint32_t anIndex = ecmascript::AnFileDataManager::GetInstance()->SafeGetFileInfoIndex(anFileName);
263             ASSERT_EQ(anIndex, 0);
264             bool res = JSNApi::Execute(vm, testAbcPath_, runtimeOptions.GetEntryPoint());
265             ASSERT_TRUE(res);
266             ASSERT_EQ(vm->GetAOTFileManager()->GetPandaFiles(0).size(), 1);
267         }
268         {
269             // simulate the case load aot file in main thread for feature-hap
270             vm->SetModuleName(workerModuleName.c_str());  // make sure the module name is the same with hap name
271             JSNApi::LoadAotFile(vm, workerModuleName);
272             uint32_t workerAnIndex =
273                 ecmascript::AnFileDataManager::GetInstance()->SafeGetFileInfoIndex(workerAnFileName);
274             ASSERT_EQ(workerAnIndex, 1);
275             bool res = JSNApi::Execute(vm, workerAbcPath_, workerRecordName_);
276             ASSERT_TRUE(res);
277             ASSERT_EQ(vm->GetAOTFileManager()->GetPandaFiles(1).size(), 1);
278         }
279         std::thread t1([&]() {
280             JSRuntimeOptions runtimeOptions;
281             runtimeOptions.SetEntryPoint(workerRecordName_);
282             EcmaVM *vm = JSNApi::CreateEcmaVM(runtimeOptions);
283             ASSERT_TRUE(vm != nullptr);
284             vm->SetModuleName(moduleName.c_str());  // assume module name for worker wont be right all the time
285             ASSERT_EQ(vm->GetAOTFileManager()->GetPandaFiles(1).size(), 0);
286             bool res = JSNApi::Execute(vm, workerAbcPath_, runtimeOptions.GetEntryPoint());
287             ASSERT_TRUE(res);
288             ASSERT_EQ(vm->GetAOTFileManager()->GetPandaFiles(1).size(), 1);
289             JSNApi::DestroyJSVM(vm);
290         });
291         {
292             ecmascript::ThreadSuspensionScope suspensionScope(vm->GetJSThread());
293             t1.join();
294         }
295 
296         JSNApi::DestroyJSVM(vm);
297     }
298 
BindPreloadedPandaFilesInAotFileTest()299     void BindPreloadedPandaFilesInAotFileTest()
300     {
301         JSRuntimeOptions runtimeOptions;
302         runtimeOptions.SetEntryPoint(testRecordName_);
303         EcmaVM *vm = JSNApi::CreateEcmaVM(runtimeOptions);
304         std::string moduleName = "file_bind_panda_file_test";
305         std::string anFileName = "file_bind_panda_file_test.an";
306         // Initialize AOT environment
307         ecmascript::AnFileDataManager::GetInstance()->SetDir(testDir_);
308         ecmascript::AnFileDataManager::GetInstance()->SetEnable(true);
309         vm->SetModuleName(moduleName.c_str());
310         JSNApi::LoadAotFile(vm, moduleName);
311         uint32_t anIndex = ecmascript::AnFileDataManager::GetInstance()->SafeGetFileInfoIndex(anFileName);
312         ASSERT_EQ(anIndex, 0);
313 
314         // 1: Normal binding process
315         {
316             // Ensure AOT file exists
317             ASSERT_TRUE(AOTFileManager::AOTFileExist(testAotPath_, AOTFileManager::FILE_EXTENSION_AN));
318             std::shared_ptr<JSPandaFile> jsPandaFile = JSPandaFileManager::GetInstance()->LoadJSPandaFile(
319                 vm->GetJSThread(), CString(testAbcPath_.c_str()), testRecordName_, false, ExecuteTypes::STATIC);
320             ASSERT_TRUE(jsPandaFile != nullptr);
321             // Perform binding
322             vm->GetAOTFileManager()->BindPreloadedPandaFilesInAotFile(testRecordName_);
323 
324             CString normalizedFileName =
325                 JSPandaFile::GetNormalizedFileDesc(CString(testAbcPath_.c_str()));
326             const auto abcFile = JSPandaFileManager::GetInstance()->FindJSPandaFileByNormalizedName(normalizedFileName);
327 
328             ASSERT_TRUE(abcFile != nullptr);
329             ASSERT_TRUE(abcFile->IsLoadedAOT());
330         }
331         // 2: aotFileInfoIndex == INVALID_INDEX
332         {
333             std::string invalidModule = "not_exist_module";
334             // Should not throw exception or bind anything
335             vm->GetAOTFileManager()->BindPreloadedPandaFilesInAotFile(invalidModule);
336             // no crash, branch is covered
337             SUCCEED();
338         }
339 
340         JSNApi::DestroyJSVM(vm);
341     }
342 
TestGetAnFileIndexCmdLineMode(const std::string & testAbcPath,const std::string & testRecordName,const std::string & testDir)343     void TestGetAnFileIndexCmdLineMode(
344         const std::string &testAbcPath,
345         const std::string &testRecordName,
346         const std::string &testDir)
347     {
348         // Branch 1: Command-line mode (WasAOTOutputFileSet is true)
349         JSRuntimeOptions cmdLineOptions;
350         cmdLineOptions.SetEntryPoint(testRecordName);
351         // Use command-line argument to set AOT output file, which sets the bitmap flag
352         const char* argv[] = {"test_program", "--aot-file", "/tmp/test_output"};
353         bool parsed = cmdLineOptions.ParseCommand(3, argv);
354         ASSERT_TRUE(parsed);
355         ASSERT_TRUE(cmdLineOptions.WasAOTOutputFileSet());
356         EcmaVM *cmdLineVM = JSNApi::CreateEcmaVM(cmdLineOptions);
357         ASSERT_TRUE(cmdLineVM != nullptr);
358         std::string moduleName = testRecordName;
359         std::string anFileName = testRecordName + ".an";
360         // Initialize AOT environment
361         ecmascript::AnFileDataManager::GetInstance()->SetDir(testDir);
362         ecmascript::AnFileDataManager::GetInstance()->SetEnable(true);
363         cmdLineVM->SetModuleName(moduleName.c_str());
364         // Load a test file
365         std::shared_ptr<JSPandaFile> jsPandaFile =
366             JSPandaFileManager::GetInstance()->LoadJSPandaFile(
367                 cmdLineVM->GetJSThread(),
368                 CString(testAbcPath.c_str()),
369                 testRecordName,
370                 false,
371                 ExecuteTypes::STATIC);
372         ASSERT_TRUE(jsPandaFile.get() != nullptr);
373         // Test command-line mode branch
374         uint32_t anIndex = cmdLineVM->GetAOTFileManager()->GetAnFileIndex(jsPandaFile.get());
375         // Should return INVALID_INDEX since file is not bound to AOT
376         ASSERT_EQ(anIndex, panda::ecmascript::INVALID_INDEX);
377         JSNApi::DestroyJSVM(cmdLineVM);
378     }
379 
TestGetAnFileIndexHapMode(const std::string & testAbcPath,const std::string & testRecordName,const std::string & testDir)380     void TestGetAnFileIndexHapMode(
381         const std::string &testAbcPath,
382         const std::string &testRecordName,
383         const std::string &testDir)
384     {
385         // Branch 2: Application HAP mode (WasAOTOutputFileSet is false)
386         JSRuntimeOptions runtimeOptions;
387         runtimeOptions.SetEntryPoint(testRecordName);
388         runtimeOptions.SetAOTOutputFile("/tmp/test_output"); // This does not set the bitmap flag
389         EcmaVM *vm = JSNApi::CreateEcmaVM(runtimeOptions);
390         std::string moduleName = testRecordName;
391         std::string anFileName = testRecordName + ".an";
392         // Initialize AOT environment
393         ecmascript::AnFileDataManager::GetInstance()->SetDir(testDir);
394         ecmascript::AnFileDataManager::GetInstance()->SetEnable(true);
395         vm->SetModuleName(moduleName.c_str());
396         // Load a test file
397         std::shared_ptr<JSPandaFile> jsPandaFile =
398             JSPandaFileManager::GetInstance()->LoadJSPandaFile(
399                 vm->GetJSThread(),
400                 CString(testAbcPath.c_str()),
401                 testRecordName,
402                 false,
403                 ExecuteTypes::STATIC);
404         ASSERT_TRUE(jsPandaFile.get() != nullptr);
405         // Verify WasAOTOutputFileSet is false
406         ASSERT_FALSE(vm->GetJSOptions().WasAOTOutputFileSet());
407         uint32_t anIndex = vm->GetAOTFileManager()->GetAnFileIndex(jsPandaFile.get());
408         ASSERT_EQ(anIndex, panda::ecmascript::INVALID_INDEX);
409         JSNApi::DestroyJSVM(vm);
410     }
411 
412     std::string testDir_ {""};
413     std::string testAbcPath_ {""};
414     std::string testRecordName_ {""};
415     std::string testApPath_ {""};
416     std::string testAnPath_ {""};
417     std::string testAiPath_ {""};
418     std::string testAotPath_ {""};
419     std::string workerAbcPath_ {""};
420     std::string workerRecordName_ {""};
421     std::string workerApPath_ {""};
422     std::string workerAnPath_ {""};
423     std::string workerAiPath_ {""};
424     std::string workerAotPath_ {""};
425     size_t testAnExpectedSize_ {0};
426 };
427 
HWTEST_F_L0(AOTFileTest,fileSizeEqualExpectedTest)428 HWTEST_F_L0(AOTFileTest, fileSizeEqualExpectedTest)
429 {
430     // This case use to test the compiler out .an file size equal to expected size by calculate.
431     // Test file use file_size_test.abc
432     std::string testFile = "file_size_test.abc";
433     SetEnvrionmentForTest(testFile);
434     GetApFileInTest(testApPath_, testRecordName_, testAbcPath_);
435     GetAnFileInTest(testApPath_, testAotPath_, testAbcPath_);
436     ASSERT_TRUE(Exists(testAnPath_));
437     ASSERT_TRUE(Exists(testAiPath_));
438     ASSERT_EQ(testAnExpectedSize_, FileSize(testAnPath_));
439 }
440 
HWTEST_F_L0(AOTFileTest,dontSaveAnFile)441 HWTEST_F_L0(AOTFileTest, dontSaveAnFile)
442 {
443     // This case use to test the compiler out .an file size less than provided limit
444     // Then generator will not save .an and .ai file
445     // Test file use file_size_test.abc
446     std::string testFile = "file_size_test.abc";
447     SetEnvrionmentForTest(testFile);
448     GetApFileInTest(testApPath_, testRecordName_, testAbcPath_);
449     GetAnFileInTest(testApPath_, testAotPath_, testAbcPath_, 1);
450     ASSERT_FALSE(Exists(testAnPath_));
451     ASSERT_FALSE(Exists(testAiPath_));
452     // We can still calculate the correct size
453     ASSERT_NE(testAnExpectedSize_, 0);
454 }
455 
HWTEST_F_L0(AOTFileTest,loadAiInMultiThread)456 HWTEST_F_L0(AOTFileTest, loadAiInMultiThread)
457 {
458     std::string testFile = "file_size_test.abc";
459     SetEnvrionmentForTest(testFile);
460     GetApFileInTest(testApPath_, testRecordName_, testAbcPath_);
461     GetAnFileInTest(testApPath_, testAotPath_, testAbcPath_);
462     ASSERT_TRUE(Exists(testAnPath_));
463     ASSERT_TRUE(Exists(testAiPath_));
464 
465     std::string workerFile = "file_size_worker.abc";
466     SetEnvrionmentForWorker(workerFile);
467     GetApFileInTest(workerApPath_, workerRecordName_, workerAbcPath_);
468     GetAnFileInTest(workerApPath_, workerAotPath_, workerAbcPath_);
469     ASSERT_TRUE(Exists(workerAnPath_));
470     ASSERT_TRUE(Exists(workerAiPath_));
471 
472     LoadAiInMultiThreadTest();
473 }
474 
HWTEST_F_L0(AOTFileTest,bindPreloadedPandaFilesInAotFileTest)475 HWTEST_F_L0(AOTFileTest, bindPreloadedPandaFilesInAotFileTest) {
476     // This test verifies the binding process of preloaded panda files in the AOT file.
477     // 1. Normal binding: ensures the AOT file exists, loads the abc file, and binds it.
478     //    Verifies that the file is correctly marked as loaded with AOT.
479     // 2. Invalid module name: calls BindPreloadedPandaFilesInAotFile with a non-existent module name,
480     //    ensures no exception or crash occurs, and the branch is covered.
481     std::string testFile = "file_bind_panda_file_test.abc";
482     SetEnvrionmentForTest(testFile);
483     GetApFileInTest(testApPath_, testRecordName_, testAbcPath_);
484     GetAnFileInTest(testApPath_, testAotPath_, testAbcPath_);
485     ASSERT_TRUE(Exists(testAnPath_));
486     ASSERT_TRUE(Exists(testAiPath_));
487     BindPreloadedPandaFilesInAotFileTest();
488 }
489 
HWTEST_F_L0(AOTFileTest,getAnFileIndexTest)490 HWTEST_F_L0(AOTFileTest, getAnFileIndexTest)
491 {
492     // This test covers GetAnFileIndex in different runtime modes.
493     // Test file: get_an_index_test.abc
494     // 1. Command-line mode: WasAOTOutputFileSet is true, should return INVALID_INDEX for unbound file.
495     // 2. Application HAP mode: WasAOTOutputFileSet is false, should also return INVALID_INDEX.
496     // Covers both branches of GetAnFileIndex related to runtime options.
497     std::string testFile = "get_an_index_test.abc";
498     SetEnvrionmentForTest(testFile);
499     GetApFileInTest(testApPath_, testRecordName_, testAbcPath_);
500     GetAnFileInTest(testApPath_, testAotPath_, testAbcPath_);
501     ASSERT_TRUE(Exists(testAnPath_));
502     ASSERT_TRUE(Exists(testAiPath_));
503     TestGetAnFileIndexCmdLineMode(testAbcPath_, testRecordName_, testDir_);
504     TestGetAnFileIndexHapMode(testAbcPath_, testRecordName_, testDir_);
505 }
506 
HWTEST_F_L0(AOTFileTest,getAbsolutePathTest)507 HWTEST_F_L0(AOTFileTest, getAbsolutePathTest)
508 {
509     // This test verifies that GetAbsolutePath returns the correct absolute path for a given abc file.
510     // Test file: file_bind_panda_file_test.abc
511     // Ensures the returned path matches the input testAbcPath_.
512     SetEnvrionmentForTest("file_bind_panda_file_test.abc");
513     EcmaVM *vm = JSNApi::CreateEcmaVM(JSRuntimeOptions());
514     ASSERT_TRUE(vm != nullptr);
515     AOTFileManager *manager = vm->GetAOTFileManager();
516     JSThread *thread = vm->GetJSThread();
517     {
518         ThreadManagedScope scope(thread);
519         // Use testAbcPath_ as the absolute path
520         JSTaggedValue absVal = thread->GetEcmaVM()->GetFactory()->NewFromASCII(testAbcPath_.c_str()).GetTaggedValue();
521         JSTaggedValue result = manager->GetAbsolutePath(thread, absVal);
522         CString resStr = ConvertToString(thread, result);
523         ASSERT_EQ(std::string(resStr.c_str()), testAbcPath_);
524     }
525     JSNApi::DestroyJSVM(vm);
526 }
527 
HWTEST_F_L0(AOTFileTest,getHeapNotNullTest)528 HWTEST_F_L0(AOTFileTest, getHeapNotNullTest)
529 {
530     // This test verifies that GetHeap returns a non-null heap pointer from AOTFileManager.
531     // Ensures the heap pointer is valid after VM creation.
532     EcmaVM *vm = JSNApi::CreateEcmaVM(JSRuntimeOptions());
533     ASSERT_TRUE(vm != nullptr);
534     AOTFileManager *manager = vm->GetAOTFileManager();
535     const Heap *heap = manager->GetHeap();
536     ASSERT_TRUE(heap != nullptr);
537     JSNApi::DestroyJSVM(vm);
538 }
539 
540 }  // namespace panda::test
541