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