1/*
2 * Copyright (c) 2024 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
16import { describe, it } from 'mocha';
17import { TransformerManager } from '../../../src/transformers/TransformerManager';
18import { assert, expect } from 'chai';
19import { FileUtils } from '../../../src/utils/FileUtils';
20import path from 'path';
21import { IOptions } from '../../../src/configs/IOptions';
22import fs from 'fs';
23import ts, {
24  TransformerFactory,
25  Node,
26  TransformationContext,
27  factory,
28  SyntaxKind,
29  CallExpression,
30  Expression,
31  CompilerOptions,
32  EmitHelper,
33  EmitHint,
34  FunctionDeclaration,
35  Identifier,
36  Statement,
37  SourceFile,
38  VariableDeclaration,
39} from 'typescript';
40import {
41  getMangleCompletePath,
42  handleNormalizedOhmUrl,
43  globalFileNameMangledTable,
44  clearCaches,
45  isInOhModules,
46  isLocalDependencyOhmUrlForTest,
47  mangleOhmUrl,
48  getMangleIncompletePathForTest,
49} from '../../../src/transformers/rename/RenameFileNameTransformer';
50import type { ProjectInfo } from '../../../src/common/type';
51import { OhmUrlStatus } from '../../../src/configs/INameObfuscationOption';
52import secharmony from '../../../src/transformers/rename/RenameFileNameTransformer';
53import { ArkObfuscator } from '../../../src/ArkObfuscator';
54
55const renameFileNameModule = require('../../../src/transformers/rename/RenameFileNameTransformer');
56const obfuscator = require('../../../src/ArkObfuscator');
57
58describe('Tester Cases for <RenameFileNameTransformer>.', function () {
59  let options;
60  let context: TransformationContext = {
61    requestEmitHelper: function (helper: EmitHelper): void {},
62    readEmitHelpers: function (): EmitHelper[] | undefined {
63      return undefined;
64    },
65    enableSubstitution: function (kind: SyntaxKind): void {},
66    isSubstitutionEnabled: function (node: Node): boolean {
67      throw new Error('Function not implemented.');
68    },
69    onSubstituteNode: function (hint: EmitHint, node: Node): Node {
70      throw new Error('Function not implemented.');
71    },
72    enableEmitNotification: function (kind: SyntaxKind): void {},
73    isEmitNotificationEnabled: function (node: Node): boolean {
74      throw new Error('Function not implemented.');
75    },
76    onEmitNode: function (hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void {
77      throw new Error('Function not implemented.');
78    },
79    factory: ts.factory,
80    getCompilerOptions: function (): CompilerOptions {
81      throw new Error('Function not implemented.');
82    },
83    startLexicalEnvironment: function (): void {},
84    suspendLexicalEnvironment: function (): void {},
85    resumeLexicalEnvironment: function (): void {},
86    endLexicalEnvironment: function (): Statement[] | undefined {
87      return undefined;
88    },
89    hoistFunctionDeclaration: function (node: FunctionDeclaration): void {},
90    hoistVariableDeclaration: function (node: Identifier): void {}
91  };
92  let node: Node;
93
94  describe('Tester Cases for <createRenameFileNameFactory>.', function () {
95    let projectInfo;
96
97    beforeEach(() => {
98      options = {
99        mRenameFileName: {
100          mEnable: true,
101          mNameGeneratorType: 1,
102          mReservedFileNames: ['file1.ts', 'file2.ts'],
103          mUniversalReservedFileNames: [],
104          mReservedProperties: ['1'],
105          mReservedToplevelNames: ['2'],
106        }
107      };
108      projectInfo = {
109        projectRootPath: '/Users/test/project',
110        packageDir: 'src/ohmodules',
111        localPackageSet: new Set<string>(),
112        useNormalized: true,
113        useTsHar: true,
114      };
115    });
116
117    it('Tester: Test initialization of config in api createRenameFileNameFactory', function () {
118      let mCustomProfiles: IOptions | undefined = FileUtils.readFileAsJson(path.join(__dirname, "obfuscate_filename_config.json"));
119      assert.strictEqual(mCustomProfiles !== undefined, true);
120      let mTransformers: TransformerFactory<Node>[] = [];
121      if (mCustomProfiles) {
122        mTransformers = new TransformerManager(mCustomProfiles).getTransformers();
123      }
124      const originalPath = 'D:/workplace/src/ets/entryability/EntryAbility.ts';
125      const mangledPath = getMangleCompletePath(originalPath);
126      assert.strictEqual(mangledPath === 'D:/workplace/src/ets/a/b.ts', true);
127    });
128
129    it('should return null if mEnable is false', () => {
130      options.mRenameFileName.mEnable = false;
131      const result = secharmony.transformerPlugin.createTransformerFactory(options);
132      expect(result).to.be.null;
133    });
134
135    it('should return null if profile is null', () => {
136      options = {};
137      const result = secharmony.transformerPlugin.createTransformerFactory(options);
138      expect(result).to.be.null;
139    });
140
141    it('should create globalFileNameMangledTable if not exist', () => {
142      const transformerFactory = secharmony.transformerPlugin.createTransformerFactory(options);
143      clearCaches();
144      renameFileNameModule.globalFileNameMangledTable = undefined;
145      const sourcefile = factory.createSourceFile([],factory.createToken(SyntaxKind.EndOfFileToken),0);
146      const transformer = transformerFactory(context);
147      const node = transformer(sourcefile);
148      expect(globalFileNameMangledTable).to.not.be.undefined;
149    })
150
151    it('should rename the node.fileName if it is a sourcefile and not in OhModules', () => {
152      ArkObfuscator.projectInfo = projectInfo;
153      obfuscator.orignalFilePathForSearching = '/Users/test/project/src/othermodules/somefile.js';
154      options.mRenameFileName.mReservedFileNames = ["D:", "workplace", "src", "ets"];
155      const transformerFactory = secharmony.transformerPlugin.createTransformerFactory(options);
156      clearCaches();
157      const sourcefile = factory.createSourceFile([], factory.createToken(SyntaxKind.EndOfFileToken), 0);
158      sourcefile.fileName = 'D:/workplace/src/ets/entryability/EntryAbility.ts';
159      const transformer = transformerFactory(context);
160      const node = transformer(sourcefile);
161      expect((node as SourceFile).fileName).to.equal('D:/workplace/src/ets/a/b.ts');
162    })
163
164    it('should update declaration if node is ImportDeclaration', () => {
165      const transformerFactory = secharmony.transformerPlugin.createTransformerFactory(options);
166      clearCaches();
167      const importdeclaration = factory.createImportDeclaration(
168        undefined, undefined, factory.createStringLiteral('ModuleInfo'), undefined);
169      const transformer = transformerFactory(context);
170      const node = transformer(importdeclaration);
171      expect(node).to.equal(importdeclaration);
172    })
173
174    it('should update declaration if node is ExportDeclaration', () => {
175      const transformerFactory = secharmony.transformerPlugin.createTransformerFactory(options);
176      clearCaches();
177      const exportdeclaration = factory.createExportDeclaration(
178        undefined, true, undefined, factory.createStringLiteral('ModuleInfo'), undefined);
179      const transformer = transformerFactory(context);
180      const node = transformer(exportdeclaration);
181      expect(node).to.equal(exportdeclaration);
182    })
183
184    it('should try update dynamic import if node is ImportCall', () => {
185      const transformerFactory = secharmony.transformerPlugin.createTransformerFactory(options);
186      clearCaches();
187      const sourceCode = `let module = import('./test');`;
188      let sourcefile = ts.createSourceFile("getNode.ts", sourceCode, ts.ScriptTarget.ES2022,false);
189      const transformer = transformerFactory(context);
190      const node = transformer(sourcefile);
191      expect(node).to.equal(sourcefile);
192    });
193
194    it('should update call expression if renamefilename', () => {
195      options.mRenameFileName.mOhmUrlStatus = OhmUrlStatus.NORMALIZED;
196      const transformerFactory = secharmony.transformerPlugin.createTransformerFactory(options);
197      clearCaches();
198      const sourceCode = `let module = import('@normalized:N&&&entry/src/main/ets/pages/test&');`;
199      let sourcefile = ts.createSourceFile("getNode.ts", sourceCode, ts.ScriptTarget.ES2022,false);
200      const transformer = transformerFactory(context);
201      const node = transformer(sourcefile);
202      expect(node).to.not.equal(sourcefile);
203    });
204  });
205
206  describe('Tester Cases for <handleNormalizedOhmUrl>.', function () {
207    beforeEach(() => {
208      options = {
209        mRenameFileName: {
210          mEnable: true,
211          mNameGeneratorType: 1,
212          mReservedFileNames: ["D:", "workplace", "src", "ets"],
213          mUniversalReservedFileNames: [],
214          mOhmUrlStatus: OhmUrlStatus.NONE,
215        }
216      };
217    });
218
219    it('should return pakName if needPkgName is true', () => {
220      secharmony.transformerPlugin.createTransformerFactory(options)(context);
221      let ohmUrl1 = '@normalized:N&&&entry/src/main/ets/pages/test&';
222      let ohmUrl2 = '@normalized:N&&&library/Index&1.0.0';
223      let ohmUrl3 = '@normalized:N&&&@abc/a/src/main/ets/pages/test&';
224
225      let pkgname1 = handleNormalizedOhmUrl(ohmUrl1, true);
226      let pkgname2 = handleNormalizedOhmUrl(ohmUrl2, true);
227      let pkgname3 = handleNormalizedOhmUrl(ohmUrl3, true);
228
229      assert.strictEqual(pkgname1, 'entry');
230      assert.strictEqual(pkgname2, 'library');
231      assert.strictEqual(pkgname3, '@abc/a');
232    });
233
234    it('should correctly normalize OhmUrl', () => {
235      secharmony.transformerPlugin.createTransformerFactory(options)(context);
236      clearCaches();
237      let ohmUrl1 = '@normalized:N&&&entry/src/main/ets/pages/test&';
238      let ohmUrl2 = '@normalized:N&&&library/Index&1.0.0';
239      let ohmUrl3 = '@normalized:N&&&@abc/a/src/main/ets/pages/test&';
240
241      let mangledOhmurl1 = handleNormalizedOhmUrl(ohmUrl1);
242      let mangledOhmurl2 = handleNormalizedOhmUrl(ohmUrl2);
243      let mangledOhmurl3 = handleNormalizedOhmUrl(ohmUrl3);
244
245      assert.strictEqual(mangledOhmurl1, '@normalized:N&&&entry/src/a/ets/b/c&');
246      assert.strictEqual(mangledOhmurl2, '@normalized:N&&&library/d&1.0.0');
247      assert.strictEqual(mangledOhmurl3, '@normalized:N&&&@abc/a/src/a/ets/b/c&');
248    });
249  });
250
251  describe('Tester Cases for <clearCaches>.', function () {
252    it('should clear globalFileNameMangledTable', function () {
253      globalFileNameMangledTable.set('key1', 'value1');
254      clearCaches();
255      expect(globalFileNameMangledTable.size).to.equal(0);
256    });
257
258    it('should clear historyFileNameMangledTable if it exists', function () {
259      renameFileNameModule.historyFileNameMangledTable = new Map<string, string>();
260      renameFileNameModule.historyFileNameMangledTable.set('key1', 'value1');
261      clearCaches();
262      expect(renameFileNameModule.historyFileNameMangledTable.size).to.equal(0);
263    });
264
265    it('should not throw an error if historyFileNameMangledTable is undefined', () => {
266      renameFileNameModule.historyFileNameMangledTable = undefined;
267      expect(() => clearCaches()).not.to.throw();
268    });
269  });
270
271  describe('Tester Cases for <isInOhModules>.', function () {
272
273    let proInfo: ProjectInfo;
274
275    beforeEach(() => {
276      proInfo = {
277        projectRootPath: '/Users/test/project',
278        packageDir: 'src/ohmodules',
279        localPackageSet: new Set<string>(),
280        useNormalized: true,
281        useTsHar: true,
282      };
283    });
284
285    it('should return true when originalPath is in the ohPackagePath', () => {
286      const originalPath = '/Users/test/project/src/ohmodules/somefile.js';
287      const result = isInOhModules(proInfo, originalPath);
288      expect(result).to.be.true;
289    });
290
291    it('should return false when originalPath is not in the ohPackagePath', () => {
292      const originalPath = '/Users/test/project/src/othermodules/somefile.js';
293      const result = isInOhModules(proInfo, originalPath);
294      expect(result).to.be.false;
295    });
296  });
297
298  describe('Tester Cases for <updateImportOrExportDeclaration>.', function () {
299
300    beforeEach(() => {
301      options = {
302        mRenameFileName: {
303          mEnable: true,
304          mNameGeneratorType: 1,
305          mReservedFileNames: ['file1.ts', 'file2.ts'],
306          mUniversalReservedFileNames: [],
307          mReservedProperties: ['1'],
308          mReservedToplevelNames: ['2'],
309          mOhmUrlStatus: OhmUrlStatus.NONE,
310        }
311      };
312    });
313
314    it('should return the same node if moduleSpecifier is missing', () => {
315      node = factory.createExportDeclaration(undefined, true, undefined);
316      secharmony.transformerPlugin.createTransformerFactory(options);
317      const result = renameFileNameModule.updateImportOrExportDeclarationForTest(node);
318      assert.deepEqual(result, node);
319    });
320
321    it('should update the moduleSpecifier of an ImportDeclaration', () => {
322      node = factory.createImportDeclaration(undefined, undefined, factory.createStringLiteral('ModuleInfo'), undefined);
323      secharmony.transformerPlugin.createTransformerFactory(options);
324      const result = renameFileNameModule.updateImportOrExportDeclarationForTest(node);
325      assert.deepEqual(result, node);
326    });
327
328    it('should update the moduleSpecifier of an ExportDeclaration', () => {
329      node = factory.createExportDeclaration(undefined, true, undefined, factory.createStringLiteral('ModuleInfo'), undefined);
330      secharmony.transformerPlugin.createTransformerFactory(options);
331      const result = renameFileNameModule.updateImportOrExportDeclarationForTest(node);
332      assert.deepEqual(result, node);
333    });
334  });
335
336  describe('Tester Cases for <isLocalDependencyOhmUrl>.', function () {
337    let projectInfo;
338
339    beforeEach(() => {
340      options = {
341        mRenameFileName: {
342          mEnable: true,
343          mNameGeneratorType: 1,
344          mReservedFileNames: ['file1.ts', 'file2.ts'],
345          mUniversalReservedFileNames: [],
346          mReservedProperties: ['1'],
347          mReservedToplevelNames: ['2'],
348          mOhmUrlStatus: OhmUrlStatus.NONE,
349        }
350      };
351      projectInfo = {
352        packageDir: 'path',
353        projectRootPath: 'rootpath',
354        localPackageSet: new Set<string>(),
355        useNormalized: false,
356        useTsHar: false,
357      };
358    });
359
360    it('should return true if mOhmUrlStatus is AT_BUNDLE or NORMALIZED', () => {
361      options.mRenameFileName.mOhmUrlStatus = OhmUrlStatus.AT_BUNDLE;
362      secharmony.transformerPlugin.createTransformerFactory(options);
363      expect(isLocalDependencyOhmUrlForTest('path/to/file')).to.be.true;
364      options.mRenameFileName.mOhmUrlStatus = OhmUrlStatus.NORMALIZED;
365      secharmony.transformerPlugin.createTransformerFactory(options);
366      expect(isLocalDependencyOhmUrlForTest('path/to/file')).to.be.true;
367    });
368
369    it('should return false if filePath does not start with NORMALIZE and useNormalized is true', () => {
370      projectInfo.useNormalized = true;
371      ArkObfuscator.projectInfo = projectInfo;
372      secharmony.transformerPlugin.createTransformerFactory(options)(context);
373      expect(isLocalDependencyOhmUrlForTest('path/to/file')).to.be.false;
374    });
375
376    it('should return true if packageName is in localPackageSet when use normalized', () => {
377      projectInfo.useNormalized = true;
378      projectInfo.localPackageSet.add('library');
379      ArkObfuscator.projectInfo = projectInfo;
380      secharmony.transformerPlugin.createTransformerFactory(options)(context);
381      expect(isLocalDependencyOhmUrlForTest('@normalized:N&&&library/Index&1.0.0')).to.be.true;
382    });
383
384    it('should return false if filePath does not start with BUNDLE and useNormalized is false', () => {
385      projectInfo.useNormalized = false;
386      ArkObfuscator.projectInfo = projectInfo;
387      secharmony.transformerPlugin.createTransformerFactory(options)(context);
388      expect(isLocalDependencyOhmUrlForTest('path/to/file')).to.be.false;
389    });
390
391    it('should return true if packageName is in localPackageSet when not use normalized', () => {
392      projectInfo.useNormalized = false;
393      projectInfo.localPackageSet.add('testName');
394      ArkObfuscator.projectInfo = projectInfo;
395      secharmony.transformerPlugin.createTransformerFactory(options)(context);
396      expect(isLocalDependencyOhmUrlForTest('@bundle:bundleName/testName/')).to.be.true;
397      expect(isLocalDependencyOhmUrlForTest('@bundle:bundleName/moduleName@testName/')).to.be.true;
398    });
399
400    it('should return false if packageName is not in localPackageSet', () => {
401      projectInfo.useNormalized = false;
402      ArkObfuscator.projectInfo = projectInfo;
403      secharmony.transformerPlugin.createTransformerFactory(options)(context);
404      expect(isLocalDependencyOhmUrlForTest('@bundle:bundleName/testName/')).to.be.false;
405      expect(isLocalDependencyOhmUrlForTest('@bundle:bundleName/moduleName@testName/')).to.be.false;
406    });
407  });
408
409  describe('Tester Cases for <getMangleCompletePath>.', function () {
410    beforeEach(() => {
411      options = {
412        mRenameFileName: {
413          mEnable: true,
414          mNameGeneratorType: 1,
415          mReservedFileNames: ["D:", "workplace", "src", "ets"],
416          mUniversalReservedFileNames: [],
417        }
418      };
419    });
420
421    it('should return a mangled file path with the same extension', () => {
422      secharmony.transformerPlugin.createTransformerFactory(options)(context);
423      const originalPath = 'D:/workplace/src/ets/entryability/EntryAbility.ts'
424      const mangledPath = getMangleCompletePath(originalPath);
425      assert.strictEqual(mangledPath === 'D:/workplace/src/ets/a/b.ts', true);
426    });
427
428    it('should reserve file names in mReservedFileNames', () => {
429      options.mRenameFileName.mReservedFileNames = ["D:", "workplace", "src", "ets", "entryability", "EntryAbility"];
430      secharmony.transformerPlugin.createTransformerFactory(options)(context);
431      const originalPath = 'D:/workplace/src/ets/entryability/EntryAbility.ts';
432      const mangledPath = getMangleCompletePath(originalPath);
433      assert.strictEqual(mangledPath === 'D:/workplace/src/ets/entryability/EntryAbility.ts', true);
434    });
435
436    it('should return history name when in historyFileNameMangledTable', () => {
437      secharmony.transformerPlugin.createTransformerFactory(options)(context);
438      renameFileNameModule.historyFileNameMangledTable = new Map<string, string>();
439      renameFileNameModule.historyFileNameMangledTable.set('entryability', 'test1');
440      const originalPath = 'D:/workplace/src/ets/entryability/EntryAbility.ts';
441      const mangledPath = getMangleCompletePath(originalPath);
442      assert.strictEqual(mangledPath === 'D:/workplace/src/ets/test1/b.ts', true);
443    });
444
445    it('should reuse name when in globalFileNameMangledTable', () => {
446      secharmony.transformerPlugin.createTransformerFactory(options)(context);
447      clearCaches();
448      const originalPath = 'D:/workplace/src/ets/entryability1/EntryAbility.ts';
449      const mangledPath = getMangleCompletePath(originalPath);
450      assert.strictEqual(mangledPath === 'D:/workplace/src/ets/a/b.ts', true);
451      const originalPath2 = 'D:/workplace/src/ets/entryability2/EntryAbility.ts';
452      const mangledPath2 = getMangleCompletePath(originalPath2);
453      assert.strictEqual(mangledPath2 === 'D:/workplace/src/ets/c/b.ts', true);
454    });
455
456    it('should return next available name when the generated name same as original name', () => {
457      secharmony.transformerPlugin.createTransformerFactory(options)(context);
458      clearCaches();
459      const originalPath = 'D:/workplace/src/ets/a.ts';
460      const mangledPath = getMangleCompletePath(originalPath);
461      assert.strictEqual(mangledPath === 'D:/workplace/src/ets/b.ts', true);
462    });
463
464    it('should return next available name when the generated name need to be reserved', () => {
465      options.mRenameFileName.mReservedFileNames = ["a", "D:", "workplace", "src", "ets"];
466      secharmony.transformerPlugin.createTransformerFactory(options)(context);
467      clearCaches();
468      const originalPath = 'D:/workplace/src/ets/entryability/EntryAbility.ts';
469      const mangledPath = getMangleCompletePath(originalPath);
470      assert.strictEqual(mangledPath === 'D:/workplace/src/ets/b/c.ts', true);
471    });
472
473    it('should return next available name when the generated name exist in globalFileNameMangledTable', () => {
474      secharmony.transformerPlugin.createTransformerFactory(options)(context);
475      clearCaches();
476      renameFileNameModule.globalFileNameMangledTable.set('testability', 'a');
477      renameFileNameModule.globalFileNameMangledTable.set('Testability', 'b');
478      const originalPath = 'D:/workplace/src/ets/entryability/EntryAbility.ts';
479      const mangledPath = getMangleCompletePath(originalPath);
480      assert.strictEqual(mangledPath === 'D:/workplace/src/ets/c/d.ts', true);
481    })
482
483    it('should return next available name when the generated name exist in historyFileNameMangledTable', () => {
484      secharmony.transformerPlugin.createTransformerFactory(options)(context);
485      clearCaches();
486      renameFileNameModule.historyFileNameMangledTable = new Map<string, string>();
487      renameFileNameModule.historyFileNameMangledTable.set('testability', 'a');
488      renameFileNameModule.historyFileNameMangledTable.set('Testability', 'b');
489      const originalPath = 'D:/workplace/src/ets/entryability/EntryAbility.ts';
490      const mangledPath = getMangleCompletePath(originalPath);
491      assert.strictEqual(mangledPath === 'D:/workplace/src/ets/c/d.ts', true);
492    })
493  });
494
495  describe('Tester Cases for <mangleOhmUrl>.', function () {
496    let projectInfo;
497
498    beforeEach(() => {
499      options = {
500        mRenameFileName: {
501          mEnable: true,
502          mNameGeneratorType: 1,
503          mReservedFileNames: ["D:", "workplace", "src", "ets"],
504          mUniversalReservedFileNames: [],
505          mOhmUrlStatus: OhmUrlStatus.NONE,
506        }
507      };
508      projectInfo = {
509        packageDir: 'path',
510        projectRootPath: 'rootpath',
511        localPackageSet: new Set<string>(),
512        useNormalized: false,
513        useTsHar: false,
514      };
515    });
516
517    it('should normalize ohmUrl if useNormalized is true', () => {
518      projectInfo.useNormalized = true;
519      ArkObfuscator.projectInfo = projectInfo;
520      secharmony.transformerPlugin.createTransformerFactory(options)(context);
521      clearCaches();
522      let ohmUrl1 = '@normalized:N&&&entry/src/main/ets/pages/test&';
523      let ohmUrl2 = '@normalized:N&&&library/Index&1.0.0';
524      let ohmUrl3 = '@normalized:N&&&@abc/a/src/main/ets/pages/test&';
525
526      let mangledOhmurl1 = mangleOhmUrl(ohmUrl1);
527      let mangledOhmurl2 = mangleOhmUrl(ohmUrl2);
528      let mangledOhmurl3 = mangleOhmUrl(ohmUrl3);
529
530      assert.strictEqual(mangledOhmurl1, '@normalized:N&&&entry/src/a/ets/b/c&');
531      assert.strictEqual(mangledOhmurl2, '@normalized:N&&&library/d&1.0.0');
532      assert.strictEqual(mangledOhmurl3, '@normalized:N&&&@abc/a/src/a/ets/b/c&');
533    });
534
535    it('should normalize ohmUrl if mOhmUrlStatus is OhmUrlStatus.NORMALIZED', () => {
536      options.mRenameFileName.mOhmUrlStatus = OhmUrlStatus.NORMALIZED;
537      secharmony.transformerPlugin.createTransformerFactory(options)(context);
538      clearCaches();
539      let ohmUrl1 = '@normalized:N&&&entry/src/main/ets/pages/test&';
540      let ohmUrl2 = '@normalized:N&&&library/Index&1.0.0';
541      let ohmUrl3 = '@normalized:N&&&@abc/a/src/main/ets/pages/test&';
542
543      let mangledOhmurl1 = mangleOhmUrl(ohmUrl1);
544      let mangledOhmurl2 = mangleOhmUrl(ohmUrl2);
545      let mangledOhmurl3 = mangleOhmUrl(ohmUrl3);
546
547      assert.strictEqual(mangledOhmurl1, '@normalized:N&&&entry/src/a/ets/b/c&');
548      assert.strictEqual(mangledOhmurl2, '@normalized:N&&&library/d&1.0.0');
549      assert.strictEqual(mangledOhmurl3, '@normalized:N&&&@abc/a/src/a/ets/b/c&');
550    });
551
552    it('should return mangled Ohm URL with fixed parts and mangled parts', () => {
553      projectInfo.useNormalized = false;
554      ArkObfuscator.projectInfo = projectInfo;
555      options.mRenameFileName.mOhmUrlStatus = OhmUrlStatus.NONE;
556      secharmony.transformerPlugin.createTransformerFactory(options)(context);
557      clearCaches();
558      let ohmUrl1 = '@normalized:N&&&entry/src/main/ets/pages/test&';
559      let ohmUrl2 = '@normalized:N&&&library/Index&1.0.0';
560      let ohmUrl3 = '@normalized:N&&&@abc/a/src/main/ets/pages/test&';
561
562      let mangledOhmurl1 = mangleOhmUrl(ohmUrl1);
563      let mangledOhmurl2 = mangleOhmUrl(ohmUrl2);
564      let mangledOhmurl3 = mangleOhmUrl(ohmUrl3);
565
566      assert.strictEqual(mangledOhmurl1, '@normalized:N&&&entry/src/a/ets/b/c');
567      assert.strictEqual(mangledOhmurl2, '@normalized:N&&&library/Index&1.0.0/');
568      assert.strictEqual(mangledOhmurl3, '@normalized:N&&&@abc/a/src/a/ets/b/c');
569    });
570  });
571
572  describe('Tester Cases for <getMangleIncompletePath>.', function () {
573    let projectInfo;
574
575    beforeEach(() => {
576      options = {
577        mRenameFileName: {
578          mEnable: true,
579          mNameGeneratorType: 1,
580          mReservedFileNames: ["D:", "workplace", "src", "ets"],
581          mUniversalReservedFileNames: [],
582          mOhmUrlStatus: OhmUrlStatus.NONE,
583        }
584      };
585      projectInfo = {
586        packageDir: 'path',
587        projectRootPath: 'rootpath',
588        localPackageSet: new Set<string>(),
589        useNormalized: false,
590        useTsHar: false,
591      };
592    });
593
594    it('should return mangled Ohm URL for local dependencies', () => {
595      projectInfo.localPackageSet.add('entry');
596      ArkObfuscator.projectInfo = projectInfo;
597      secharmony.transformerPlugin.createTransformerFactory(options)(context);
598      clearCaches();
599      let ohmUrl = '@bundle:com.example.myapplication/entry/index';
600      let mangledOhmurl = getMangleIncompletePathForTest(ohmUrl);
601      assert.strictEqual(mangledOhmurl, '@bundle:com.example.myapplication/entry/a');
602    });
603
604    it('should return the original path if it is not a valid file path and not a local dependency', () => {
605      secharmony.transformerPlugin.createTransformerFactory(options)(context);
606      clearCaches();
607      let path = '/workplace/src/ets/entryability/EntryAbility';
608      let mangledPath = getMangleIncompletePathForTest(path);
609      assert.strictEqual(mangledPath, '/workplace/src/ets/entryability/EntryAbility');
610    });
611
612    it('should return mangled directory name without extension', () => {
613      secharmony.transformerPlugin.createTransformerFactory(options)(context);
614      obfuscator.orignalFilePathForSearching = '';
615      clearCaches();
616      let path = 'test/ut/transformer/demo.ts';
617      fs.writeFileSync(path, 'test');
618      let path1 = 'test/ut/transformer/demo';
619      let mangledPath = getMangleIncompletePathForTest(path1);
620      assert.strictEqual(mangledPath, 'a/b/c/d');
621      fs.unlinkSync(path);
622    });
623
624    it('should return mangled file path with extension for valid file paths', () => {
625      secharmony.transformerPlugin.createTransformerFactory(options)(context);
626      obfuscator.orignalFilePathForSearching = '';
627      clearCaches();
628      let path = 'test/ut/transformer/demo.ts';
629      fs.writeFileSync(path, 'test');
630      let path1 = 'test/ut/transformer/demo.ts';
631      let mangledPath = getMangleIncompletePathForTest(path1);
632      assert.strictEqual(mangledPath, 'a/b/c/d.ts');
633      fs.unlinkSync(path);
634    });
635  });
636});
637