1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "assembler/assembly-emitter.h"
17 #include "assembler/assembly-parser.h"
18 #include "libpandafile/class_data_accessor-inl.h"
19
20 #include "ecmascript/base/path_helper.h"
21 #include "ecmascript/global_env.h"
22 #include "ecmascript/jspandafile/js_pandafile.h"
23 #include "ecmascript/jspandafile/js_pandafile_manager.h"
24 #include "ecmascript/jspandafile/program_object.h"
25 #include "ecmascript/module/js_module_manager.h"
26 #include "ecmascript/module/js_module_source_text.h"
27 #include "ecmascript/module/module_data_extractor.h"
28 #include "ecmascript/module/module_path_helper.h"
29 #include "ecmascript/tests/test_helper.h"
30 #include "ecmascript/linked_hash_table.h"
31
32
33 using namespace panda::ecmascript;
34 using namespace panda::panda_file;
35 using namespace panda::pandasm;
36
37 namespace panda::test {
38 class EcmaModuleTest : 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) << "TearDownCase";
48 }
49
SetUp()50 void SetUp() override
51 {
52 TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
53 }
54
TearDown()55 void TearDown() override
56 {
57 TestHelper::DestroyEcmaVMWithScope(instance, scope);
58 }
59 EcmaVM *instance {nullptr};
60 ecmascript::EcmaHandleScope *scope {nullptr};
61 JSThread *thread {nullptr};
62 };
63
64 /*
65 * Feature: Module
66 * Function: AddImportEntry
67 * SubFunction: AddImportEntry
68 * FunctionPoints: Add import entry
69 * CaseDescription: Add two import item and check module import entries size
70 */
HWTEST_F_L0(EcmaModuleTest,AddImportEntry)71 HWTEST_F_L0(EcmaModuleTest, AddImportEntry)
72 {
73 ObjectFactory *objectFactory = thread->GetEcmaVM()->GetFactory();
74 JSHandle<SourceTextModule> module = objectFactory->NewSourceTextModule();
75 JSHandle<ImportEntry> importEntry1 = objectFactory->NewImportEntry();
76 SourceTextModule::AddImportEntry(thread, module, importEntry1, 0, 2);
77 JSHandle<ImportEntry> importEntry2 = objectFactory->NewImportEntry();
78 SourceTextModule::AddImportEntry(thread, module, importEntry2, 1, 2);
79 JSHandle<TaggedArray> importEntries(thread, module->GetImportEntries());
80 EXPECT_TRUE(importEntries->GetLength() == 2U);
81 }
82
83 /*
84 * Feature: Module
85 * Function: AddLocalExportEntry
86 * SubFunction: AddLocalExportEntry
87 * FunctionPoints: Add local export entry
88 * CaseDescription: Add two local export item and check module local export entries size
89 */
HWTEST_F_L0(EcmaModuleTest,AddLocalExportEntry)90 HWTEST_F_L0(EcmaModuleTest, AddLocalExportEntry)
91 {
92 ObjectFactory *objectFactory = thread->GetEcmaVM()->GetFactory();
93 JSHandle<SourceTextModule> module = objectFactory->NewSourceTextModule();
94 JSHandle<LocalExportEntry> localExportEntry1 = objectFactory->NewLocalExportEntry();
95 SourceTextModule::AddLocalExportEntry(thread, module, localExportEntry1, 0, 2);
96 JSHandle<LocalExportEntry> localExportEntry2 = objectFactory->NewLocalExportEntry();
97 SourceTextModule::AddLocalExportEntry(thread, module, localExportEntry2, 1, 2);
98 JSHandle<TaggedArray> localExportEntries(thread, module->GetLocalExportEntries());
99 EXPECT_TRUE(localExportEntries->GetLength() == 2U);
100 }
101
102 /*
103 * Feature: Module
104 * Function: AddIndirectExportEntry
105 * SubFunction: AddIndirectExportEntry
106 * FunctionPoints: Add indirect export entry
107 * CaseDescription: Add two indirect export item and check module indirect export entries size
108 */
HWTEST_F_L0(EcmaModuleTest,AddIndirectExportEntry)109 HWTEST_F_L0(EcmaModuleTest, AddIndirectExportEntry)
110 {
111 ObjectFactory *objectFactory = thread->GetEcmaVM()->GetFactory();
112 JSHandle<SourceTextModule> module = objectFactory->NewSourceTextModule();
113 JSHandle<IndirectExportEntry> indirectExportEntry1 = objectFactory->NewIndirectExportEntry();
114 SourceTextModule::AddIndirectExportEntry(thread, module, indirectExportEntry1, 0, 2);
115 JSHandle<IndirectExportEntry> indirectExportEntry2 = objectFactory->NewIndirectExportEntry();
116 SourceTextModule::AddIndirectExportEntry(thread, module, indirectExportEntry2, 1, 2);
117 JSHandle<TaggedArray> indirectExportEntries(thread, module->GetIndirectExportEntries());
118 EXPECT_TRUE(indirectExportEntries->GetLength() == 2U);
119 }
120
121 /*
122 * Feature: Module
123 * Function: StarExportEntries
124 * SubFunction: StarExportEntries
125 * FunctionPoints: Add start export entry
126 * CaseDescription: Add two start export item and check module start export entries size
127 */
HWTEST_F_L0(EcmaModuleTest,AddStarExportEntry)128 HWTEST_F_L0(EcmaModuleTest, AddStarExportEntry)
129 {
130 ObjectFactory *objectFactory = thread->GetEcmaVM()->GetFactory();
131 JSHandle<SourceTextModule> module = objectFactory->NewSourceTextModule();
132 JSHandle<StarExportEntry> starExportEntry1 = objectFactory->NewStarExportEntry();
133 SourceTextModule::AddStarExportEntry(thread, module, starExportEntry1, 0, 2);
134 JSHandle<StarExportEntry> starExportEntry2 = objectFactory->NewStarExportEntry();
135 SourceTextModule::AddStarExportEntry(thread, module, starExportEntry2, 1, 2);
136 JSHandle<TaggedArray> startExportEntries(thread, module->GetStarExportEntries());
137 EXPECT_TRUE(startExportEntries->GetLength() == 2U);
138 }
139
140 /*
141 * Feature: Module
142 * Function: StoreModuleValue
143 * SubFunction: StoreModuleValue/GetModuleValue
144 * FunctionPoints: store a module export item in module
145 * CaseDescription: Simulated implementation of "export foo as bar", set foo as "hello world",
146 * use "import bar" in same js file
147 */
HWTEST_F_L0(EcmaModuleTest,StoreModuleValue)148 HWTEST_F_L0(EcmaModuleTest, StoreModuleValue)
149 {
150 ObjectFactory* objFactory = thread->GetEcmaVM()->GetFactory();
151 CString localName = "foo";
152 CString exportName = "bar";
153 CString value = "hello world";
154
155 JSHandle<JSTaggedValue> localNameHandle = JSHandle<JSTaggedValue>::Cast(objFactory->NewFromUtf8(localName));
156 JSHandle<JSTaggedValue> exportNameHandle = JSHandle<JSTaggedValue>::Cast(objFactory->NewFromUtf8(exportName));
157 JSHandle<LocalExportEntry> localExportEntry =
158 objFactory->NewLocalExportEntry(exportNameHandle, localNameHandle, LocalExportEntry::LOCAL_DEFAULT_INDEX);
159 JSHandle<SourceTextModule> module = objFactory->NewSourceTextModule();
160 SourceTextModule::AddLocalExportEntry(thread, module, localExportEntry, 0, 1);
161
162 JSHandle<JSTaggedValue> storeKey = JSHandle<JSTaggedValue>::Cast(objFactory->NewFromUtf8(localName));
163 JSHandle<JSTaggedValue> valueHandle = JSHandle<JSTaggedValue>::Cast(objFactory->NewFromUtf8(value));
164 module->StoreModuleValue(thread, storeKey, valueHandle);
165
166 JSHandle<JSTaggedValue> loadKey = JSHandle<JSTaggedValue>::Cast(objFactory->NewFromUtf8(localName));
167 JSTaggedValue loadValue = module->GetModuleValue(thread, loadKey.GetTaggedValue(), false);
168 EXPECT_EQ(valueHandle.GetTaggedValue(), loadValue);
169 }
170
171 /*
172 * Feature: Module
173 * Function: GetModuleValue
174 * SubFunction: StoreModuleValue/GetModuleValue
175 * FunctionPoints: load module value from module
176 * CaseDescription: Simulated implementation of "export default let foo = 'hello world'",
177 * use "import C from 'xxx' to get default value"
178 */
HWTEST_F_L0(EcmaModuleTest,GetModuleValue)179 HWTEST_F_L0(EcmaModuleTest, GetModuleValue)
180 {
181 ObjectFactory* objFactory = thread->GetEcmaVM()->GetFactory();
182 // export entry
183 CString exportLocalName = "*default*";
184 CString exportName = "default";
185 CString exportValue = "hello world";
186 JSHandle<JSTaggedValue> exportLocalNameHandle =
187 JSHandle<JSTaggedValue>::Cast(objFactory->NewFromUtf8(exportLocalName));
188 JSHandle<JSTaggedValue> exportNameHandle =
189 JSHandle<JSTaggedValue>::Cast(objFactory->NewFromUtf8(exportName));
190 JSHandle<LocalExportEntry> localExportEntry = objFactory->NewLocalExportEntry(exportNameHandle,
191 exportLocalNameHandle, LocalExportEntry::LOCAL_DEFAULT_INDEX);
192 JSHandle<SourceTextModule> moduleExport = objFactory->NewSourceTextModule();
193 SourceTextModule::AddLocalExportEntry(thread, moduleExport, localExportEntry, 0, 1);
194 // store module value
195 JSHandle<JSTaggedValue> exportValueHandle = JSHandle<JSTaggedValue>::Cast(objFactory->NewFromUtf8(exportValue));
196 moduleExport->StoreModuleValue(thread, exportLocalNameHandle, exportValueHandle);
197
198 JSTaggedValue importDefaultValue =
199 moduleExport->GetModuleValue(thread, exportLocalNameHandle.GetTaggedValue(), false);
200 EXPECT_EQ(exportValueHandle.GetTaggedValue(), importDefaultValue);
201 }
202
HWTEST_F_L0(EcmaModuleTest,GetRecordName1)203 HWTEST_F_L0(EcmaModuleTest, GetRecordName1)
204 {
205 std::string baseFileName = MODULE_ABC_PATH "module_test_module_test_module_base.abc";
206
207 JSNApi::EnableUserUncaughtErrorHandler(instance);
208
209 bool result = JSNApi::Execute(instance, baseFileName, "module_test_module_test_module_base");
210 EXPECT_TRUE(result);
211 }
212
HWTEST_F_L0(EcmaModuleTest,GetRecordName2)213 HWTEST_F_L0(EcmaModuleTest, GetRecordName2)
214 {
215 std::string baseFileName = MODULE_ABC_PATH "module_test_module_test_A.abc";
216
217 JSNApi::EnableUserUncaughtErrorHandler(instance);
218
219 bool result = JSNApi::Execute(instance, baseFileName, "module_test_module_test_A");
220 EXPECT_TRUE(result);
221 }
222
HWTEST_F_L0(EcmaModuleTest,GetExportObjectIndex)223 HWTEST_F_L0(EcmaModuleTest, GetExportObjectIndex)
224 {
225 std::string baseFileName = MODULE_ABC_PATH "module_test_module_test_C.abc";
226
227 JSNApi::EnableUserUncaughtErrorHandler(instance);
228
229 bool result = JSNApi::Execute(instance, baseFileName, "module_test_module_test_C");
230 JSNApi::GetExportObject(instance, "module_test_module_test_B", "a");
231 EXPECT_TRUE(result);
232 }
233
HWTEST_F_L0(EcmaModuleTest,HostResolveImportedModule)234 HWTEST_F_L0(EcmaModuleTest, HostResolveImportedModule)
235 {
236 std::string baseFileName = MODULE_ABC_PATH "module_test_module_test_C.abc";
237
238 JSNApi::EnableUserUncaughtErrorHandler(instance);
239
240 ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
241 ObjectFactory *factory = instance->GetFactory();
242 JSHandle<SourceTextModule> module = factory->NewSourceTextModule();
243 JSHandle<JSTaggedValue> moduleRecord(thread, module.GetTaggedValue());
244 moduleManager->AddResolveImportedModule(baseFileName.c_str(), moduleRecord);
245 JSHandle<JSTaggedValue> res = moduleManager->HostResolveImportedModule(baseFileName.c_str());
246
247 EXPECT_EQ(moduleRecord->GetRawData(), res.GetTaggedValue().GetRawData());
248 }
249
HWTEST_F_L0(EcmaModuleTest,PreventExtensions_IsExtensible)250 HWTEST_F_L0(EcmaModuleTest, PreventExtensions_IsExtensible)
251 {
252 ObjectFactory *objectFactory = thread->GetEcmaVM()->GetFactory();
253 JSHandle<SourceTextModule> module = objectFactory->NewSourceTextModule();
254 JSHandle<LocalExportEntry> localExportEntry1 = objectFactory->NewLocalExportEntry();
255 SourceTextModule::AddLocalExportEntry(thread, module, localExportEntry1, 0, 2);
256 JSHandle<LocalExportEntry> localExportEntry2 = objectFactory->NewLocalExportEntry();
257 SourceTextModule::AddLocalExportEntry(thread, module, localExportEntry2, 1, 2);
258 JSHandle<TaggedArray> localExportEntries(thread, module->GetLocalExportEntries());
259 CString baseFileName = "a.abc";
260 JSHandle<EcmaString> moduleFilename = objectFactory->NewFromUtf8(baseFileName);
261 module->SetEcmaModuleFilename(thread, moduleFilename);
262 ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
263 moduleManager->AddResolveImportedModule(baseFileName, JSHandle<JSTaggedValue>::Cast(module));
264 JSHandle<ModuleNamespace> np =
265 ModuleNamespace::ModuleNamespaceCreate(thread, JSHandle<JSTaggedValue>::Cast(module), localExportEntries);
266 EXPECT_FALSE(np->IsExtensible());
267 EXPECT_TRUE(ModuleNamespace::PreventExtensions());
268 }
269
HWTEST_F_L0(EcmaModuleTest,Instantiate_Evaluate_GetNamespace_SetNamespace)270 HWTEST_F_L0(EcmaModuleTest, Instantiate_Evaluate_GetNamespace_SetNamespace)
271 {
272 std::string baseFileName = MODULE_ABC_PATH "module_test_module_test_C.abc";
273
274 JSNApi::EnableUserUncaughtErrorHandler(instance);
275
276 bool result = JSNApi::Execute(instance, baseFileName, "module_test_module_test_C");
277 EXPECT_TRUE(result);
278 ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
279 JSHandle<SourceTextModule> module = moduleManager->HostGetImportedModule("module_test_module_test_C");
280 module->SetStatus(ModuleStatus::UNINSTANTIATED);
281 ModuleRecord::Instantiate(thread, JSHandle<JSTaggedValue>(module));
282 JSTaggedValue res = ModuleRecord::Evaluate(thread, JSHandle<JSTaggedValue>(module));
283 ModuleRecord::GetNamespace(module.GetTaggedValue());
284 ModuleRecord::SetNamespace(thread, module.GetTaggedValue(), JSTaggedValue::Undefined());
285 EXPECT_TRUE(res.IsJSPromise());
286 }
287
HWTEST_F_L0(EcmaModuleTest,ConcatFileNameWithMerge1)288 HWTEST_F_L0(EcmaModuleTest, ConcatFileNameWithMerge1)
289 {
290 CString baseFilename = "merge.abc";
291 const char *data = R"(
292 .language ECMAScript
293 .function any func_main_0(any a0, any a1, any a2) {
294 ldai 1
295 return
296 }
297 )";
298 JSPandaFileManager *pfManager = JSPandaFileManager::GetInstance();
299 Parser parser;
300 auto res = parser.Parse(data);
301 std::unique_ptr<const File> pfPtr = pandasm::AsmEmitter::Emit(res.Value());
302 std::shared_ptr<JSPandaFile> pf = pfManager->NewJSPandaFile(pfPtr.release(), baseFilename);
303
304 // Test moduleRequestName start with "@bundle"
305 CString moduleRecordName = "moduleTest1";
306 CString moduleRequestName = "@bundle:com.bundleName.test/moduleName/requestModuleName1";
307 CString result = "com.bundleName.test/moduleName/requestModuleName1";
308 CString entryPoint = ModulePathHelper::ConcatFileNameWithMerge(thread, pf.get(), baseFilename, moduleRecordName,
309 moduleRequestName);
310 EXPECT_EQ(result, entryPoint);
311
312 // Test cross application
313 moduleRecordName = "@bundle:com.bundleName1.test/moduleName/requestModuleName1";
314 CString newBaseFileName = "/data/storage/el1/bundle/com.bundleName.test/moduleName/moduleName/ets/modules.abc";
315 ModulePathHelper::ConcatFileNameWithMerge(thread, pf.get(), baseFilename, moduleRecordName, moduleRequestName);
316 EXPECT_EQ(baseFilename, newBaseFileName);
317 }
318
HWTEST_F_L0(EcmaModuleTest,ConcatFileNameWithMerge2)319 HWTEST_F_L0(EcmaModuleTest, ConcatFileNameWithMerge2)
320 {
321 CString baseFilename = "merge.abc";
322 const char *data = R"(
323 .language ECMAScript
324 .function any func_main_0(any a0, any a1, any a2) {
325 ldai 1
326 return
327 }
328 )";
329 JSPandaFileManager *pfManager = JSPandaFileManager::GetInstance();
330 Parser parser;
331 auto res = parser.Parse(data);
332 std::unique_ptr<const File> pfPtr = pandasm::AsmEmitter::Emit(res.Value());
333 std::shared_ptr<JSPandaFile> pf = pfManager->NewJSPandaFile(pfPtr.release(), baseFilename);
334
335 // Test moduleRequestName start with "./"
336 CString moduleRecordName = "moduleTest2";
337 CString moduleRequestName = "./requestModule.js";
338 CString result = "requestModule";
339 pf->InsertJSRecordInfo(result);
340 CString entryPoint = ModulePathHelper::ConcatFileNameWithMerge(thread, pf.get(), baseFilename, moduleRecordName,
341 moduleRequestName);
342 EXPECT_EQ(result, entryPoint);
343
344 // Test moduleRecordName with "/"
345 moduleRecordName = "moduleName/moduleTest2";
346 moduleRequestName = "./requestModule.js";
347 result = "moduleName/requestModule";
348 pf->InsertJSRecordInfo(result);
349 entryPoint = ModulePathHelper::ConcatFileNameWithMerge(
350 thread, pf.get(), baseFilename, moduleRecordName, moduleRequestName);
351 EXPECT_EQ(result, entryPoint);
352 }
353
HWTEST_F_L0(EcmaModuleTest,ConcatFileNameWithMerge3)354 HWTEST_F_L0(EcmaModuleTest, ConcatFileNameWithMerge3)
355 {
356 CString baseFilename = "merge.abc";
357 const char *data = R"(
358 .language ECMAScript
359 .function any func_main_0(any a0, any a1, any a2) {
360 ldai 1
361 return
362 }
363 )";
364 JSPandaFileManager *pfManager = JSPandaFileManager::GetInstance();
365 Parser parser;
366 auto res = parser.Parse(data);
367 std::unique_ptr<const File> pfPtr = pandasm::AsmEmitter::Emit(res.Value());
368 std::shared_ptr<JSPandaFile> pf = pfManager->NewJSPandaFile(pfPtr.release(), baseFilename);
369
370 // Test RecordName is not in JSPandaFile
371 CString moduleRecordName = "moduleTest3";
372 CString moduleRequestName = "./secord.js";
373 CString result = "secord";
374 CString requestFileName = "secord.abc";
375 CString entryPoint =
376 ModulePathHelper::ConcatFileNameWithMerge(thread, pf.get(), baseFilename, moduleRecordName, moduleRequestName);
377 EXPECT_EQ(baseFilename, requestFileName);
378 EXPECT_EQ(result, entryPoint);
379
380 // Test RecordName is not in JSPandaFile and baseFilename with "/" and moduleRequestName with "/"
381 baseFilename = "test/merge.abc";
382 std::unique_ptr<const File> pfPtr2 = pandasm::AsmEmitter::Emit(res.Value());
383 std::shared_ptr<JSPandaFile> pf2 = pfManager->NewJSPandaFile(pfPtr2.release(), baseFilename);
384
385 moduleRecordName = "moduleTest3";
386 moduleRequestName = "./test/secord.js";
387 result = "secord";
388 requestFileName = "test/test/secord.abc";
389 entryPoint = ModulePathHelper::ConcatFileNameWithMerge(thread, pf2.get(), baseFilename, moduleRecordName,
390 moduleRequestName);
391 EXPECT_EQ(baseFilename, requestFileName);
392 EXPECT_EQ(result, entryPoint);
393 }
394
HWTEST_F_L0(EcmaModuleTest,ConcatFileNameWithMerge4)395 HWTEST_F_L0(EcmaModuleTest, ConcatFileNameWithMerge4)
396 {
397 CString baseFilename = "merge.abc";
398 const char *data = R"(
399 .language ECMAScript
400 .function any func_main_0(any a0, any a1, any a2) {
401 ldai 1
402 return
403 }
404 )";
405 JSPandaFileManager *pfManager = JSPandaFileManager::GetInstance();
406 Parser parser;
407 auto res = parser.Parse(data);
408 std::unique_ptr<const File> pfPtr = pandasm::AsmEmitter::Emit(res.Value());
409 std::shared_ptr<JSPandaFile> pf = pfManager->NewJSPandaFile(pfPtr.release(), baseFilename);
410 const CUnorderedMap<CString, JSPandaFile::JSRecordInfo> &recordInfo = pf->GetJSRecordInfo();
411 // Test moduleRequestName is npm package
412 CString moduleRecordName = "node_modules/0/moduleTest4/index";
413 CString moduleRequestName = "json/index";
414 CString result = "node_modules/0/moduleTest4/node_modules/json/index";
415 JSPandaFile::JSRecordInfo info;
416 info.npmPackageName = "node_modules/0/moduleTest4";
417 const_cast<CUnorderedMap<CString, JSPandaFile::JSRecordInfo> &>(recordInfo).insert({moduleRecordName, info});
418 const_cast<CUnorderedMap<CString, JSPandaFile::JSRecordInfo> &>(recordInfo).insert({result, info});
419 CString entryPoint = ModulePathHelper::ConcatFileNameWithMerge(thread, pf.get(), baseFilename, moduleRecordName,
420 moduleRequestName);
421 EXPECT_EQ(result, entryPoint);
422 }
423
HWTEST_F_L0(EcmaModuleTest,NormalizePath)424 HWTEST_F_L0(EcmaModuleTest, NormalizePath)
425 {
426 CString res1 = "node_modules/0/moduleTest/index";
427 CString moduleRecordName1 = "node_modules///0//moduleTest/index";
428
429 CString res2 = "node_modules/0/moduleTest/index";
430 CString moduleRecordName2 = "./node_modules///0//moduleTest/index";
431
432 CString res3 = "node_modules/0/moduleTest/index";
433 CString moduleRecordName3 = "../node_modules/0/moduleTest///index";
434
435 CString res4 = "moduleTest/index";
436 CString moduleRecordName4 = "./node_modules/..//moduleTest////index";
437
438 CString res5 = "node_modules/moduleTest/index";
439 CString moduleRecordName5 = "node_modules/moduleTest/index/";
440
441 CString normalName1 = PathHelper::NormalizePath(moduleRecordName1);
442 CString normalName2 = PathHelper::NormalizePath(moduleRecordName2);
443 CString normalName3 = PathHelper::NormalizePath(moduleRecordName3);
444 CString normalName4 = PathHelper::NormalizePath(moduleRecordName4);
445 CString normalName5 = PathHelper::NormalizePath(moduleRecordName5);
446
447 EXPECT_EQ(res1, normalName1);
448 EXPECT_EQ(res2, normalName2);
449 EXPECT_EQ(res3, normalName3);
450 EXPECT_EQ(res4, normalName4);
451 EXPECT_EQ(res5, normalName5);
452 }
453
HWTEST_F_L0(EcmaModuleTest,ParseOhmUrl)454 HWTEST_F_L0(EcmaModuleTest, ParseOhmUrl)
455 {
456 // old pages url
457 instance->SetBundleName("com.bundleName.test");
458 instance->SetModuleName("moduleName");
459 CString inputFileName = "moduleName/ets/pages/index.abc";
460 CString outFileName = "";
461 CString res1 = "com.bundleName.test/moduleName/ets/pages/index";
462 CString entryPoint;
463 ModulePathHelper::ParseOhmUrl(instance, inputFileName, outFileName, entryPoint);
464 EXPECT_EQ(entryPoint, res1);
465 EXPECT_EQ(outFileName, "");
466
467 // new pages url
468 inputFileName = "@bundle:com.bundleName.test/moduleName/ets/pages/index.abc";
469 ModulePathHelper::ParseOhmUrl(instance, inputFileName, outFileName, entryPoint);
470 EXPECT_EQ(entryPoint, res1);
471 EXPECT_EQ(outFileName, "/data/storage/el1/bundle/moduleName/ets/modules.abc");
472
473 // new pages url Intra-application cross hap
474 inputFileName = "@bundle:com.bundleName.test/moduleName1/ets/pages/index.abc";
475 CString outRes = "/data/storage/el1/bundle/moduleName1/ets/modules.abc";
476 CString res2 = "com.bundleName.test/moduleName1/ets/pages/index";
477 ModulePathHelper::ParseOhmUrl(instance, inputFileName, outFileName, entryPoint);
478 EXPECT_EQ(entryPoint, res2);
479 EXPECT_EQ(outFileName, outRes);
480
481 // new pages url Cross-application
482 inputFileName = "@bundle:com.bundleName.test1/moduleName1/ets/pages/index.abc";
483 CString outRes1 = "/data/storage/el1/bundle/com.bundleName.test1/moduleName1/moduleName1/ets/modules.abc";
484 CString res3 = "com.bundleName.test1/moduleName1/ets/pages/index";
485 ModulePathHelper::ParseOhmUrl(instance, inputFileName, outFileName, entryPoint);
486 EXPECT_EQ(entryPoint, res3);
487 EXPECT_EQ(outFileName, outRes1);
488
489 // worker url Intra-application cross hap
490 inputFileName = "/data/storage/el1/bundle/entry/ets/mainAbility.abc";
491 CString outRes2 = "/data/storage/el1/bundle/entry/ets/modules.abc";
492 CString res4 = "com.bundleName.test/entry/ets/mainAbility";
493 ModulePathHelper::ParseOhmUrl(instance, inputFileName, outFileName, entryPoint);
494 EXPECT_EQ(entryPoint, res4);
495 EXPECT_EQ(outFileName, outRes2);
496
497 // worker url
498 outFileName = "";
499 inputFileName = "/data/storage/el1/bundle/moduleName/ets/mainAbility.abc";
500 CString res5 = "com.bundleName.test/moduleName/ets/mainAbility";
501 ModulePathHelper::ParseOhmUrl(instance, inputFileName, outFileName, entryPoint);
502 EXPECT_EQ(entryPoint, res5);
503 EXPECT_EQ(outFileName, "/data/storage/el1/bundle/moduleName/ets/modules.abc");
504 }
505
HWTEST_F_L0(EcmaModuleTest,CheckNativeModule)506 HWTEST_F_L0(EcmaModuleTest, CheckNativeModule)
507 {
508 // load file
509 CString requestName1 = "@bundle:bundleName/moduleName/ets/index";
510
511 // load native modules
512 CString requestName2 = "@ohos:router";
513 CString requestName3 = "@app:bundleName/moduleName/lib*.so";
514 CString requestName4 = "@native:system.app";
515 CString requestName5 = "@xxx:internal";
516
517 // load npm Packages
518 CString requestName6 = "@package:pkg_modules/.ohpm/json5@2.2.3/pkg_modules/json5/dist/index";
519 CString requestName7 = "@ohos/common";
520
521 std::pair<bool, ModuleTypes> res1 = SourceTextModule::CheckNativeModule(requestName1);
522 EXPECT_EQ(res1.first, false);
523 EXPECT_EQ(res1.second, ModuleTypes::UNKNOWN);
524
525 std::pair<bool, ModuleTypes> res2 = SourceTextModule::CheckNativeModule(requestName2);
526 EXPECT_EQ(res2.first, true);
527 EXPECT_EQ(res2.second, ModuleTypes::OHOS_MODULE);
528
529 std::pair<bool, ModuleTypes> res3 = SourceTextModule::CheckNativeModule(requestName3);
530 EXPECT_EQ(res3.first, true);
531 EXPECT_EQ(res3.second, ModuleTypes::APP_MODULE);
532
533 std::pair<bool, ModuleTypes> res4 = SourceTextModule::CheckNativeModule(requestName4);
534 EXPECT_EQ(res4.first, true);
535 EXPECT_EQ(res4.second, ModuleTypes::NATIVE_MODULE);
536
537 std::pair<bool, ModuleTypes> res5 = SourceTextModule::CheckNativeModule(requestName5);
538 EXPECT_EQ(res5.first, true);
539 EXPECT_EQ(res5.second, ModuleTypes::INTERNAL_MODULE);
540
541 std::pair<bool, ModuleTypes> res6 = SourceTextModule::CheckNativeModule(requestName6);
542 EXPECT_EQ(res6.first, false);
543 EXPECT_EQ(res6.second, ModuleTypes::UNKNOWN);
544
545 std::pair<bool, ModuleTypes> res7 = SourceTextModule::CheckNativeModule(requestName7);
546 EXPECT_EQ(res7.first, false);
547 EXPECT_EQ(res7.second, ModuleTypes::UNKNOWN);
548 }
549
HWTEST_F_L0(EcmaModuleTest,ResolveDirPath)550 HWTEST_F_L0(EcmaModuleTest, ResolveDirPath)
551 {
552 ObjectFactory *objectFactory = thread->GetEcmaVM()->GetFactory();
553
554 CString inputFileName = "moduleName/ets/pages/index.abc";
555 CString resName1 = "moduleName/ets/pages/";
556 JSHandle<EcmaString> res1 = objectFactory->NewFromUtf8(resName1);
557 JSHandle<EcmaString> outFileName = PathHelper::ResolveDirPath(thread, inputFileName);
558 EXPECT_EQ(outFileName, res1);
559
560 inputFileName = "moduleName\\ets\\pages\\index.abc";
561 CString resName2 = "moduleName\\ets\\pages\\";
562 JSHandle<EcmaString> res2 = objectFactory->NewFromUtf8(resName2);
563 outFileName = PathHelper::ResolveDirPath(thread, inputFileName);
564 EXPECT_EQ(outFileName, res2);
565
566 inputFileName = "cjs";
567 CString resName3 = "";
568 JSHandle<EcmaString> res3 = objectFactory->NewFromUtf8(resName3);
569 outFileName = PathHelper::ResolveDirPath(thread, inputFileName);
570 EXPECT_EQ(outFileName, res3);
571 }
572
HWTEST_F_L0(EcmaModuleTest,DeleteNamespace)573 HWTEST_F_L0(EcmaModuleTest, DeleteNamespace)
574 {
575 CString inputFileName = "moduleName@nameSpace";
576 CString res1 = "moduleName";
577 PathHelper::DeleteNamespace(inputFileName);
578 EXPECT_EQ(inputFileName, res1);
579
580 inputFileName = "moduleName";
581 CString res2 = "moduleName";
582 PathHelper::DeleteNamespace(inputFileName);
583 EXPECT_EQ(inputFileName, res2);
584 }
585
HWTEST_F_L0(EcmaModuleTest,AdaptOldIsaRecord)586 HWTEST_F_L0(EcmaModuleTest, AdaptOldIsaRecord)
587 {
588 CString inputFileName = "bundleName/moduleName@namespace/moduleName";
589 CString res1 = "moduleName";
590 PathHelper::AdaptOldIsaRecord(inputFileName);
591 EXPECT_EQ(inputFileName, res1);
592 }
593
HWTEST_F_L0(EcmaModuleTest,GetStrippedModuleName)594 HWTEST_F_L0(EcmaModuleTest, GetStrippedModuleName)
595 {
596 CString inputFileName = "@ohos:hilog";
597 CString res1 = "hilog";
598 CString outFileName = PathHelper::GetStrippedModuleName(inputFileName);
599 EXPECT_EQ(outFileName, res1);
600 }
601
HWTEST_F_L0(EcmaModuleTest,GetInternalModulePrefix)602 HWTEST_F_L0(EcmaModuleTest, GetInternalModulePrefix)
603 {
604 CString inputFileName = "@ohos:hilog";
605 CString res1 = "ohos";
606 CString outFileName = PathHelper::GetInternalModulePrefix(inputFileName);
607 EXPECT_EQ(outFileName, res1);
608 }
609
HWTEST_F_L0(EcmaModuleTest,IsNativeModuleRequest)610 HWTEST_F_L0(EcmaModuleTest, IsNativeModuleRequest)
611 {
612 CString inputFileName = "json5";
613 bool res1 = ModulePathHelper::IsNativeModuleRequest(inputFileName);
614 EXPECT_TRUE(!res1);
615
616 inputFileName = "@ohos:hilog";
617 bool res2 = ModulePathHelper::IsNativeModuleRequest(inputFileName);
618 EXPECT_TRUE(res2);
619
620 inputFileName = "@app:xxxx";
621 bool res3 = ModulePathHelper::IsNativeModuleRequest(inputFileName);
622 EXPECT_TRUE(res3);
623
624 inputFileName = "@native:xxxx";
625 bool res4 = ModulePathHelper::IsNativeModuleRequest(inputFileName);
626 EXPECT_TRUE(res4);
627 }
628
HWTEST_F_L0(EcmaModuleTest,IsImportFile)629 HWTEST_F_L0(EcmaModuleTest, IsImportFile)
630 {
631 CString inputFileName = "./test";
632 bool res1 = ModulePathHelper::IsImportFile(inputFileName);
633 EXPECT_TRUE(res1);
634 CString outFileName = ModulePathHelper::RemoveSuffix(inputFileName);
635 EXPECT_EQ(outFileName, inputFileName);
636
637 inputFileName = "test";
638 bool res2 = ModulePathHelper::IsImportFile(inputFileName);
639 EXPECT_TRUE(!res2);
640 outFileName = ModulePathHelper::RemoveSuffix(inputFileName);
641 EXPECT_EQ(outFileName, inputFileName);
642
643 CString result = "test";
644 inputFileName = "test.js";
645 bool res3 = ModulePathHelper::IsImportFile(inputFileName);
646 EXPECT_TRUE(res3);
647 outFileName = ModulePathHelper::RemoveSuffix(inputFileName);
648 EXPECT_EQ(outFileName, result);
649
650 inputFileName = "test.ts";
651 bool res4 = ModulePathHelper::IsImportFile(inputFileName);
652 EXPECT_TRUE(res4);
653 outFileName = ModulePathHelper::RemoveSuffix(inputFileName);
654 EXPECT_EQ(outFileName, result);
655
656 inputFileName = "test.ets";
657 bool res5 = ModulePathHelper::IsImportFile(inputFileName);
658 EXPECT_TRUE(res5);
659 outFileName = ModulePathHelper::RemoveSuffix(inputFileName);
660 EXPECT_EQ(outFileName, result);
661
662 inputFileName = "test.json";
663 bool res6 = ModulePathHelper::IsImportFile(inputFileName);
664 EXPECT_TRUE(res6);
665 outFileName = ModulePathHelper::RemoveSuffix(inputFileName);
666 EXPECT_EQ(outFileName, result);
667 }
668 } // namespace panda::test
669