• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use rollupObject 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// Execute this file first to avoid circular dependency problems
17
18import { expect } from 'chai';
19import mocha from 'mocha';
20import fs, { unwatchFile } from "fs";
21import path from "path";
22import MagicString from 'magic-string';
23import sinon from 'sinon';
24
25import {
26  getBuildModeInLowerCase,
27  getPackageInfo,
28  genSourceMapFileName,
29  isOhModules,
30  isEs2Abc,
31  writeArkguardObfuscatedSourceCode,
32  writeMinimizedSourceCode,
33  tryMangleFileName,
34  getPreviousStageSourceMap,
35  collectObfuscationFileContent
36} from '../../lib/ark_utils';
37import {
38  DEBUG,
39  RELEASE,
40  OH_MODULES,
41  EXTNAME_TS,
42  EXTNAME_JS,
43  EXTNAME_ETS,
44  OBFUSCATION_TOOL
45} from '../../lib/fast_build/ark_compiler/common/ark_define';
46import RollUpPluginMock from './mock/rollup_mock/rollup_plugin_mock';
47import {
48  BUNDLE_NAME_DEFAULT,
49  ENTRY_MODULE_NAME_DEFAULT,
50  EXTNAME_MAP,
51  ENTRYABILITY_JS
52} from './mock/rollup_mock/common';
53import projectConfig from './utils/processProjectConfig';
54import {
55  ES2ABC,
56  TS2ABC
57} from '../../lib/pre_define';
58import { changeFileExtension } from '../../lib/fast_build/ark_compiler/utils';
59import ModuleSourceFileMock from './mock/class_mock/module_source_files_mock';
60import {
61  genTemporaryPath,
62  toUnixPath
63} from '../../lib/utils';
64import {
65  ObConfigResolver,
66  MergedConfig,
67  obfLogger
68} from '../../lib/fast_build/ark_compiler/common/ob_config_resolver';
69import {
70  utProcessArkConfig
71} from '../../lib/fast_build/ark_compiler/common/process_ark_config';
72import { ModuleSourceFile } from '../../lib/fast_build/ark_compiler/module/module_source_file';
73import { PROJECT_ROOT, TERSER_PROCESSED_EXPECTED_CODE } from './mock/rollup_mock/path_config';
74import { GEN_ABC_PLUGIN_NAME } from '../../lib/fast_build/ark_compiler/common/ark_define';
75import { SourceMapGenerator } from '../../lib/fast_build/ark_compiler/generate_sourcemap';
76import { ArkObfuscator } from 'arkguard';
77import {
78  ArkTSInternalErrorDescription,
79  ErrorCode
80} from '../../lib/fast_build/ark_compiler/error_code';
81import {
82  CommonLogger,
83  LogData,
84  LogDataFactory
85} from '../../lib/fast_build/ark_compiler/logger';
86import { initObfLogger, printObfLogger } from '../../lib/fast_build/ark_compiler/common/ob_config_resolver';
87import { getLogger } from 'log4js';
88import { createErrInfo } from './utils/utils';
89
90mocha.describe('test ark_utils file api', function () {
91  mocha.before(function () {
92    this.rollup = new RollUpPluginMock();
93  });
94
95  mocha.after(() => {
96    delete this.rollup;
97  });
98
99  mocha.it('1-1: test getBuildModeInLowerCase under build debug', function () {
100    this.rollup.build();
101    const buildMode = getBuildModeInLowerCase(this.rollup.share.projectConfig);
102    expect(buildMode === DEBUG).to.be.true;
103  });
104
105  mocha.it('1-2: test getBuildModeInLowerCase under build release', function () {
106    this.rollup.build(RELEASE);
107    const buildMode = getBuildModeInLowerCase(this.rollup.share.projectConfig);
108    expect(buildMode === RELEASE).to.be.true;
109  });
110
111  mocha.it('1-3: test getBuildModeInLowerCase under preview debug', function () {
112    this.rollup.preview();
113    const buildMode = getBuildModeInLowerCase(this.rollup.share.projectConfig);
114    expect(buildMode === DEBUG).to.be.true;
115  });
116
117  mocha.it('1-4: test getBuildModeInLowerCase under hot reload debug', function () {
118    this.rollup.hotReload();
119    const buildMode = getBuildModeInLowerCase(this.rollup.share.projectConfig);
120    expect(buildMode === DEBUG).to.be.true;
121  });
122
123  mocha.it('2-1: test getPackageInfo under build debug', function () {
124    this.rollup.build();
125    const returnInfo = getPackageInfo(this.rollup.share.projectConfig.aceModuleJsonPath);
126    expect(returnInfo[0] === BUNDLE_NAME_DEFAULT).to.be.true;
127    expect(returnInfo[1] === ENTRY_MODULE_NAME_DEFAULT).to.be.true;
128  });
129
130  mocha.it('2-2: test getPackageInfo under build release', function () {
131    this.rollup.build(RELEASE);
132    const returnInfo = getPackageInfo(this.rollup.share.projectConfig.aceModuleJsonPath);
133    expect(returnInfo[0] === BUNDLE_NAME_DEFAULT).to.be.true;
134    expect(returnInfo[1] === ENTRY_MODULE_NAME_DEFAULT).to.be.true;
135  });
136
137  mocha.it('2-3: test getPackageInfo under preview debug', function () {
138    this.rollup.preview();
139    const returnInfo = getPackageInfo(this.rollup.share.projectConfig.aceModuleJsonPath);
140    expect(returnInfo[0] === BUNDLE_NAME_DEFAULT).to.be.true;
141    expect(returnInfo[1] === ENTRY_MODULE_NAME_DEFAULT).to.be.true;
142  });
143
144  mocha.it('2-4: test getPackageInfo under hot reload debug', function () {
145    this.rollup.hotReload();
146    const returnInfo = getPackageInfo(this.rollup.share.projectConfig.aceModuleJsonPath);
147    expect(returnInfo[0] === BUNDLE_NAME_DEFAULT).to.be.true;
148    expect(returnInfo[1] === ENTRY_MODULE_NAME_DEFAULT).to.be.true;
149  });
150
151  mocha.it('3-1: test genSourceMapFileName under build debug', function () {
152    this.rollup.build();
153    for (const filePath of this.rollup.share.allFiles) {
154      if (filePath.endsWith(EXTNAME_TS) || filePath.endsWith(EXTNAME_JS)) {
155        const originPath = genSourceMapFileName(filePath);
156        const expectedPath = `${filePath}${EXTNAME_MAP}`;
157        expect(originPath === expectedPath).to.be.true;
158      } else if (filePath.endsWith(EXTNAME_ETS)) {
159        const originPath = genSourceMapFileName(filePath);
160        expect(originPath === filePath).to.be.true;
161      }
162    }
163  });
164
165  mocha.it('3-2: test genSourceMapFileName under build release', function () {
166    this.rollup.build(RELEASE);
167    for (const filePath of this.rollup.share.allFiles) {
168      if (filePath.endsWith(EXTNAME_TS) || filePath.endsWith(EXTNAME_JS)) {
169        const originPath = genSourceMapFileName(filePath);
170        const expectedPath = `${filePath}${EXTNAME_MAP}`;
171        expect(originPath === expectedPath).to.be.true;
172      }
173    }
174  });
175
176  mocha.it('3-3: test genSourceMapFileName under preview debug', function () {
177    this.rollup.preview();
178    for (const filePath of this.rollup.share.allFiles) {
179      if (filePath.endsWith(EXTNAME_TS) || filePath.endsWith(EXTNAME_JS)) {
180        const originPath = genSourceMapFileName(filePath);
181        const expectedPath = `${filePath}${EXTNAME_MAP}`;
182        expect(originPath === expectedPath).to.be.true;
183      }
184    }
185  });
186
187  mocha.it('3-4: test genSourceMapFileName under hot reload debug', function () {
188    this.rollup.hotReload();
189    for (const filePath of this.rollup.share.allFiles) {
190      if (filePath.endsWith(EXTNAME_TS) || filePath.endsWith(EXTNAME_JS)) {
191        const originPath = genSourceMapFileName(filePath);
192        const expectedPath = `${filePath}${EXTNAME_MAP}`;
193        expect(originPath === expectedPath).to.be.true;
194      }
195    }
196  });
197
198  mocha.it('4-1: test isOhModules under build debug', function () {
199    this.rollup.build();
200    const returnInfo = isOhModules(this.rollup.share.projectConfig);
201    expect(returnInfo === false).to.be.true;
202    this.rollup.share.projectConfig.packageDir = OH_MODULES;
203    const returnInfoOh = isOhModules(this.rollup.share.projectConfig);
204    expect(returnInfoOh).to.be.true;
205  });
206
207  mocha.it('4-2: test isOhModules under build release', function () {
208    this.rollup.build(RELEASE);
209    const returnInfo = isOhModules(this.rollup.share.projectConfig);
210    expect(returnInfo === false).to.be.true;
211    this.rollup.share.projectConfig.packageDir = OH_MODULES;
212    const returnInfoOh = isOhModules(this.rollup.share.projectConfig);
213    expect(returnInfoOh).to.be.true;
214  });
215
216  mocha.it('4-3: test isOhModules under preview debug', function () {
217    this.rollup.preview();
218    const returnInfo = isOhModules(this.rollup.share.projectConfig);
219    expect(returnInfo === false).to.be.true;
220    this.rollup.share.projectConfig.packageDir = OH_MODULES;
221    const returnInfoOh = isOhModules(this.rollup.share.projectConfig);
222    expect(returnInfoOh).to.be.true;
223  });
224
225  mocha.it('4-4: test isOhModules under hot reload debug', function () {
226    this.rollup.hotReload();
227    const returnInfo = isOhModules(this.rollup.share.projectConfig);
228    expect(returnInfo === false).to.be.true;
229    this.rollup.share.projectConfig.packageDir = OH_MODULES;
230    const returnInfoOh = isOhModules(this.rollup.share.projectConfig);
231    expect(returnInfoOh).to.be.true;
232  });
233
234  mocha.it('4-5: test isOhModules under hot fix debug', function () {
235    projectConfig.buildMode = DEBUG;
236    const returnInfo = isOhModules(projectConfig);
237    expect(returnInfo).to.be.true;
238  });
239
240  mocha.it('4-6: test isOhModules under hot fix release', function () {
241    projectConfig.buildMode = RELEASE;
242    const returnInfo = isOhModules(projectConfig);
243    expect(returnInfo).to.be.true;
244  });
245
246  mocha.it('5-1: test isEs2Abc under build debug', function () {
247    this.rollup.build();
248    this.rollup.share.projectConfig.pandaMode = ES2ABC;
249    const returnInfo = isEs2Abc(this.rollup.share.projectConfig);
250    expect(returnInfo).to.be.true;
251
252    this.rollup.share.projectConfig.pandaMode = TS2ABC;
253    const returnInfoTS2ABC = isEs2Abc(this.rollup.share.projectConfig);
254    expect(returnInfoTS2ABC === false).to.be.true;
255
256    this.rollup.share.projectConfig.pandaMode = "undefined";
257    const returnInfoUndef = isEs2Abc(this.rollup.share.projectConfig);
258    expect(returnInfoUndef).to.be.true;
259
260    this.rollup.share.projectConfig.pandaMode = undefined;
261    const returnInfoUndefined = isEs2Abc(this.rollup.share.projectConfig);
262    expect(returnInfoUndefined).to.be.true;
263  });
264
265  mocha.it('5-2: test isEs2Abc under build release', function () {
266    this.rollup.build(RELEASE);
267    this.rollup.share.projectConfig.pandaMode = ES2ABC;
268    const returnInfo = isEs2Abc(this.rollup.share.projectConfig);
269    expect(returnInfo).to.be.true;
270
271    this.rollup.share.projectConfig.pandaMode = TS2ABC;
272    const returnInfoTS2ABC = isEs2Abc(this.rollup.share.projectConfig);
273    expect(returnInfoTS2ABC).to.be.false;
274  });
275
276  mocha.it('5-3: test isEs2Abc under preview debug', function () {
277    this.rollup.preview();
278    this.rollup.share.projectConfig.pandaMode = ES2ABC;
279    const returnInfo = isEs2Abc(this.rollup.share.projectConfig);
280    expect(returnInfo).to.be.true;
281
282    this.rollup.share.projectConfig.pandaMode = TS2ABC;
283    const returnInfoTS2ABC = isEs2Abc(this.rollup.share.projectConfig);
284    expect(returnInfoTS2ABC).to.be.false;
285  });
286
287  mocha.it('5-4: test isEs2Abc under hot reload debug', function () {
288    this.rollup.hotReload();
289    this.rollup.share.projectConfig.pandaMode = ES2ABC;
290    const returnInfo = isEs2Abc(this.rollup.share.projectConfig);
291    expect(returnInfo).to.be.true;
292
293    this.rollup.share.projectConfig.pandaMode = TS2ABC;
294    const returnInfoTS2ABC = isEs2Abc(this.rollup.share.projectConfig);
295    expect(returnInfoTS2ABC).to.be.false;
296  });
297
298  mocha.it('5-5: test isEs2Abc under hot fix debug', function () {
299    projectConfig.buildMode = DEBUG;
300    projectConfig.pandaMode = ES2ABC;
301    const returnInfo = isEs2Abc(projectConfig);
302    expect(returnInfo).to.be.true;
303
304    projectConfig.pandaMode = TS2ABC;
305    const returnInfoTS2ABC = isEs2Abc(projectConfig);
306    expect(returnInfoTS2ABC).to.be.false;
307  });
308
309  mocha.it('5-6: test isEs2Abc under hot fix release', function () {
310    projectConfig.buildMode = RELEASE;
311    projectConfig.pandaMode = ES2ABC;
312    const returnInfo = isEs2Abc(projectConfig);
313    expect(returnInfo).to.be.true;
314
315    projectConfig.pandaMode = TS2ABC;
316    const returnInfoTS2ABC = isEs2Abc(projectConfig);
317    expect(returnInfoTS2ABC).to.be.false;
318  });
319
320  mocha.it('6-1: test the error message of writeArkguardObfuscatedSourceCode', async function () {
321    this.rollup.build(RELEASE);
322    SourceMapGenerator.initInstance(this.rollup);
323    this.rollup.share.getHvigorConsoleLogger = undefined;
324    initObfLogger(this.rollup.share);
325    const stub = sinon.stub(obfLogger, 'error');
326    const red: string = '\x1B[31m';
327    try {
328      await writeArkguardObfuscatedSourceCode(
329        {content: undefined, buildFilePath: '', relativeSourceFilePath: '', originSourceFilePath: ''},
330        printObfLogger, this.rollup.share.projectConfig, {});
331    } catch (e) {
332    }
333    expect(stub.calledWith(red,
334      `ArkTS:INTERNAL ERROR: Failed to obfuscate file '' with arkguard. TypeError: Cannot read properties of undefined (reading 'obfuscate')`
335    )).to.be.true;
336    stub.restore();
337    SourceMapGenerator.cleanSourceMapObject();
338  });
339
340  mocha.it('6-2: test the error message of writeArkguardObfuscatedSourceCode' +
341    'with getHvigorConsoleLogger', async function () {
342    this.rollup.build(RELEASE);
343    SourceMapGenerator.initInstance(this.rollup);
344    class customShare {
345      public getHvigorConsoleLogger(prefix: string) {
346       const logger = hvigorLogger.getLogger(prefix);
347       return logger;
348     }
349    }
350    class hvigorLogger {
351      mSubSystem: string = '';
352      constructor(subSystem: string) {
353        this.mSubSystem = subSystem;
354      }
355
356      public printError(errInfo: Object) {
357      }
358
359      public static getLogger(subSystem): hvigorLogger {
360        return new hvigorLogger(subSystem);
361      }
362    }
363    initObfLogger(new customShare());
364    const stub = sinon.stub(obfLogger, 'printError');
365    try {
366      await writeArkguardObfuscatedSourceCode(
367        {content: undefined, buildFilePath: '', relativeSourceFilePath: '', originSourceFilePath: ''},
368        printObfLogger, this.rollup.share.projectConfig, {});
369    } catch (e) {
370    }
371    const info = {
372        code: '10810001',
373        description: 'ArkTS compiler Error',
374        cause: "ArkTS:INTERNAL ERROR: Failed to obfuscate file '' with arkguard. TypeError: Cannot read properties of undefined (reading 'obfuscate')",
375        position: '',
376        solutions: [ 'Please modify the code based on the error information.' ]
377    };
378    expect(stub.calledWith(info)).to.be.true;
379    stub.restore();
380    SourceMapGenerator.cleanSourceMapObject();
381  });
382
383  mocha.it('7-1: test the error message of writeMinimizedSourceCode', async function () {
384    this.rollup.build(RELEASE);
385    const errInfo: LogData = LogDataFactory.newInstance(
386      ErrorCode.ETS2BUNDLE_INTERNAL_SOURCE_CODE_OBFUSCATION_FAILED,
387      ArkTSInternalErrorDescription,
388      'Failed to obfuscate source code for filePath'
389    );
390    const logger = CommonLogger.getInstance(this.rollup);
391    const stub = sinon.stub(logger.getLoggerFromErrorCode(errInfo.code), 'printError');
392    try {
393      await writeMinimizedSourceCode(undefined, 'filePath', logger);
394    } catch (e) {
395    }
396    expect(stub.calledWith(errInfo)).to.be.true;
397    stub.restore();
398  });
399
400  mocha.it('7-2: test the error message of writeMinimizedSourceCode without getHvigorConsoleLogger', async function () {
401    this.rollup.build(RELEASE);
402    const errInfo: LogData = LogDataFactory.newInstance(
403      ErrorCode.ETS2BUNDLE_INTERNAL_SOURCE_CODE_OBFUSCATION_FAILED,
404      ArkTSInternalErrorDescription,
405      'Failed to obfuscate source code for filePath'
406    );
407    CommonLogger.destroyInstance();
408    const getHvigorConsoleLogger = this.rollup.share.getHvigorConsoleLogger;
409    this.rollup.share.getHvigorConsoleLogger = undefined;
410    const logger = CommonLogger.getInstance(this.rollup);
411    const stub = sinon.stub(logger.logger, 'error');
412    try {
413      await writeMinimizedSourceCode(undefined, 'filePath', logger);
414    } catch (e) {
415    }
416    expect(stub.calledWith(errInfo.toString())).to.be.true;
417    CommonLogger.destroyInstance();
418    this.rollup.share.getHvigorConsoleLogger = getHvigorConsoleLogger;
419    stub.restore();
420  });
421
422  mocha.it('8-1: test tryMangleFileName when obfuscation is disabled', async function () {
423    const filePath = '/mnt/application/entry/build/default/cache/default/default@CompileArkTS/esmodule/release/src/main/ets/entryability/EntryAbility.ts';
424    const originalFilePath = '/mnt/application/entry/src/main/ets/entryability/EntryAbility.ets';
425    const projectConfig = {
426      projectRootPath: '/mnt/application',
427      packageDir: 'oh_modules',
428      modulePathMap: {
429        entry: '/mnt/application/entry'
430      },
431      obfuscationMergedObConfig: {
432        options: {
433          enableFileNameObfuscation: false
434        }
435      }
436    }
437    const result = tryMangleFileName(filePath, projectConfig, originalFilePath);
438    expect(result === filePath).to.be.true;
439  });
440
441  mocha.it('8-2: test tryMangleFileName when obfuscation is enabled', async function () {
442    const filePath = '/mnt/application/entry/build/default/cache/default/default@CompileArkTS/esmodule/release/src/main/ets/entryability/EntryAbility.ts';
443    const originalFilePath = '/mnt/application/entry/src/main/ets/entryability/EntryAbility.ets';
444    const newFilePath = '/mnt/application/entry/build/default/cache/default/default@CompileArkTS/esmodule/release/src/main/ets/a/b.ts';
445    const projectConfig = {
446      projectRootPath: '/mnt/application',
447      packageDir: 'oh_modules',
448      modulePathMap: {
449        entry: '/mnt/application/entry'
450      },
451      obfuscationMergedObConfig: {
452        options: {
453          enableFileNameObfuscation: true
454        }
455      }
456    }
457
458    const printerConfig = {
459      //Print obfuscation time&memory usage of all files and obfuscation processes
460      mFilesPrinter: false,
461      //Print time&memory usage of a single file obfuscation in transform processes
462      mSingleFilePrinter: false,
463      //Print sum up time of transform processes during obfuscation
464      mSumPrinter: false,
465      //Output path of printer
466      mOutputPath: ""
467    }
468
469    const arkguardConfig = {
470      mRenameFileName: {
471        mEnable: true,
472        mNameGeneratorType: 1,
473        mReservedFileNames: [
474          'entry',
475          'mnt',
476          'application',
477          'entry',
478          'src',
479          'main',
480          'ets',
481          'build',
482          'default',
483          'cache',
484          'default',
485          'default@CompileArkTS',
486          'esmodule',
487          'release'
488        ],
489      },
490      mPerformancePrinter: printerConfig
491    }
492
493    let arkObfuscator: ArkObfuscator = new ArkObfuscator();
494    arkObfuscator.init(arkguardConfig);
495    const content = `function foo() {}`
496    const obfuscateResult = arkObfuscator.obfuscate(content, filePath, undefined);
497    obfuscateResult.then(result => {
498      const afterObfuscateFilePath = result.filePath;
499      expect(afterObfuscateFilePath === newFilePath).to.be.true;
500    })
501
502    const result = tryMangleFileName(filePath, projectConfig, originalFilePath);
503    expect(result === newFilePath).to.be.true;
504  });
505
506  mocha.it('8-3: test tryMangleFileName when bytecode obfuscation is enabled', async function () {
507    const filePath = '/mnt/application/entry/build/default/cache/default/default@CompileArkTS/esmodule/release/src/main/ets/entryability/EntryAbility.ts';
508    const originalFilePath = '/mnt/application/entry/src/main/ets/entryability/EntryAbility.ets';
509    const projectConfig = {
510      projectRootPath: '/mnt/application',
511      packageDir: 'oh_modules',
512      modulePathMap: {
513        entry: '/mnt/application/entry'
514      },
515      obfuscationMergedObConfig: {
516        options: {
517          enableFileNameObfuscation: true
518        }
519      },
520      isArkguardEnabled: false,
521      isBytecodeObfEnabled: true
522    }
523    const result = tryMangleFileName(filePath, projectConfig, originalFilePath, projectConfig.isBytecodeObfEnabled);
524    expect(result === filePath).to.be.true;
525    projectConfig.isBytecodeObfEnabled = false
526  });
527
528  mocha.it('9-1: test writeArkguardObfuscatedSourceCode when obfuscation is enabled', async function () {
529    this.rollup.build(RELEASE);
530    const logger = this.rollup.share.getLogger(GEN_ABC_PLUGIN_NAME);
531    const arkguardConfig = {
532      mCompact: false,
533      mDisableConsole: false,
534      mSimplify: false,
535      mRemoveComments: true,
536      mNameObfuscation: {
537        mEnable: true,
538        mNameGeneratorType: 1,
539        mReservedNames: [],
540        mRenameProperties: false,
541        mReservedProperties: [],
542        mKeepStringProperty: true,
543        mTopLevel: false,
544        mReservedToplevelNames: [],
545        mUniversalReservedProperties: [],
546        mUniversalReservedToplevelNames: [],
547      },
548      mRemoveDeclarationComments: {
549        mEnable: true,
550        mReservedComments: []
551      },
552      mEnableSourceMap: true,
553      mEnableNameCache: true,
554      mRenameFileName: {
555        mEnable: false,
556        mNameGeneratorType: 1,
557        mReservedFileNames: [],
558      },
559      mExportObfuscation: false,
560      mPerformancePrinter: {
561        mFilesPrinter: false,
562        mSingleFilePrinter: false,
563        mSumPrinter: false,
564        mOutputPath: ""
565      },
566      mKeepFileSourceCode: {
567        mKeepSourceOfPaths: new Set(),
568        mkeepFilesAndDependencies: new Set(),
569      },
570    };
571
572    const sourceMapGenerator: SourceMapGenerator = SourceMapGenerator.initInstance(this.rollup);
573    sourceMapGenerator.setNewSoureMaps(false);
574    const arkObfuscator: ArkObfuscator = new ArkObfuscator();
575    arkObfuscator.init(arkguardConfig);
576
577    const projectConfig = {
578      projectRootPath: PROJECT_ROOT,
579      arkObfuscator: arkObfuscator,
580      packageDir: 'oh_modules',
581      localPackageSet: new Set(),
582      useTsHar: false,
583      useNormalized: false
584    };
585
586    const sourceFileName = 'sourceFile.ts';
587    const originalSourceFilePath = path.join(__dirname, '../../test/ark_compiler_ut/testdata/har_obfuscation', sourceFileName);
588    const moduleInfo = {
589      content: fs.readFileSync(originalSourceFilePath, 'utf-8'),
590      buildFilePath: `${PROJECT_ROOT}/har_obfuscation/build/default/cache/${sourceFileName}`,
591      relativeSourceFilePath: `har_obfuscation/${sourceFileName}`,
592      originSourceFilePath: originalSourceFilePath,
593      rollupModuleId: originalSourceFilePath
594    };
595
596    try {
597      await writeArkguardObfuscatedSourceCode(moduleInfo, logger, projectConfig, undefined);
598    } catch (e) {
599    }
600    const expectedResult = `export function add(d: number, e: number): number {
601    return d + e;
602}
603export function findElement<a>(b: a[], c: (item: a) => boolean): a | undefined {
604    return b.find(c);
605}
606`;
607    const result = fs.readFileSync(moduleInfo.buildFilePath, 'utf-8');
608    expect(result === expectedResult).to.be.true;
609
610    const declFileName = 'sourceFile.d.ts';
611    const originalDeclFilePath = path.join(__dirname, '../../test/ark_compiler_ut/testdata/har_obfuscation/', declFileName);
612
613    const declModuleInfo = {
614      content: fs.readFileSync(originalDeclFilePath, 'utf-8'),
615      buildFilePath: `${PROJECT_ROOT}/har_obfuscation/build/default/cache/${declFileName}`,
616      relativeSourceFilePath: `har_obfuscation/build/default/cache/${declFileName}`,
617      originSourceFilePath: originalSourceFilePath,
618      rollupModuleId: originalSourceFilePath
619    };
620
621    try {
622      await writeArkguardObfuscatedSourceCode(declModuleInfo, logger, projectConfig, undefined);
623    } catch (e) {
624    }
625
626    const expectedDeclResult = `export declare function add(d: number, e: number): number;
627export declare function findElement<a>(b: a[], c: (item: a) => boolean): a | undefined;
628`;
629    const declResult = fs.readFileSync(declModuleInfo.buildFilePath, 'utf-8');
630    expect(declResult === expectedDeclResult).to.be.true;
631  });
632
633  mocha.describe('10: test getPreviousStageSourceMap', function() {
634    let sourceMapGeneratorStub;
635    mocha.beforeEach(function () {
636      sourceMapGeneratorStub = sinon.stub(SourceMapGenerator, 'getInstance');
637    });
638
639    mocha.afterEach(() => {
640      sinon.restore();
641    });
642
643    mocha.it('10-1: should return undefined if relativeSourceFilePath is empty', async function () {
644      const moduleInfo = {
645        buildFilePath: 'file.js',
646        relativeSourceFilePath: '',
647        rollupModuleId: 'moduleId'
648      };
649      const result = getPreviousStageSourceMap(moduleInfo);
650      expect(result).to.be.undefined;
651    });
652
653    mocha.it('10-2: should return undefined if the file is a declaration file', function() {
654      const moduleInfo = {
655        buildFilePath: 'file.d.ts',
656        relativeSourceFilePath: 'sourceFile.ts',
657        rollupModuleId: 'moduleId'
658      };
659      const result = getPreviousStageSourceMap(moduleInfo);
660      expect(result).to.be.undefined;
661    });
662
663    mocha.it('10-3: should call getSpecifySourceMap with rollupModuleId if isNewSourceMaps is true', function() {
664      const fakeSourceMap = {};
665      const instanceStub = {
666        isNewSourceMaps: sinon.stub().returns(true),
667        getSpecifySourceMap: sinon.stub().returns(fakeSourceMap)
668      };
669      sourceMapGeneratorStub.returns(instanceStub);
670
671      const moduleInfo = {
672        buildFilePath: 'file.js',
673        relativeSourceFilePath: 'sourceFile.ts',
674        rollupModuleId: 'moduleId'
675      };
676      const result = getPreviousStageSourceMap(moduleInfo);
677
678      expect(instanceStub.getSpecifySourceMap.calledWith({}, 'moduleId')).to.be.true;
679      expect(result).to.equal(fakeSourceMap);
680    });
681
682    mocha.it('10-4: should call getSpecifySourceMap with relativeSourceFilePath if isNewSourceMaps is false', function() {
683      const fakeSourceMap = {};
684      const instanceStub = {
685        isNewSourceMaps: sinon.stub().returns(false),
686        getSpecifySourceMap: sinon.stub().returns(fakeSourceMap)
687      };
688      sourceMapGeneratorStub.returns(instanceStub);
689
690      const moduleInfo = {
691        buildFilePath: 'file.js',
692        relativeSourceFilePath: 'sourceFile.ts',
693        rollupModuleId: 'moduleId'
694      };
695      const result = getPreviousStageSourceMap(moduleInfo);
696
697      expect(instanceStub.getSpecifySourceMap.calledWith({}, 'sourceFile.ts')).to.be.true;
698      expect(result).to.equal(fakeSourceMap);
699    });
700  })
701  mocha.describe('11: test collectObfuscationFileContent', function () {
702    let fileContentManagerStub;
703
704    mocha.beforeEach(function () {
705      fileContentManagerStub = {
706        updateFileContent: sinon.stub(),
707      };
708    });
709
710    mocha.afterEach(function () {
711      sinon.restore();
712    });
713
714    mocha.it('11-1: should not call updateFileContent if filePathManager is not defined', function () {
715      const moduleInfo = {
716        buildFilePath: 'file.js',
717        originSourceFilePath: 'sourceFile.ts',
718      };
719      const projectConfig = {
720        arkObfuscator: {},
721      };
722      const previousStageSourceMap = {};
723
724      collectObfuscationFileContent(moduleInfo, projectConfig, previousStageSourceMap);
725
726      expect(fileContentManagerStub.updateFileContent.called).to.be.false;
727    });
728
729    mocha.it('11-2: should not call updateFileContent if the file is a declaration file and not an original declaration file', function () {
730      const moduleInfo = {
731        buildFilePath: 'file.d.ts',
732        originSourceFilePath: 'sourceFile.ts',
733      };
734      const projectConfig = {
735        arkObfuscator: {
736          filePathManager: {},
737          fileContentManager: fileContentManagerStub,
738        },
739      };
740      const previousStageSourceMap = {};
741
742      collectObfuscationFileContent(moduleInfo, projectConfig, previousStageSourceMap);
743
744      expect(fileContentManagerStub.updateFileContent.called).to.be.false;
745    });
746
747    mocha.it('11-3: should call updateFileContent if the file is not a declaration file', function () {
748      const moduleInfo = {
749        buildFilePath: 'file.js',
750        originSourceFilePath: 'sourceFile.ts',
751      };
752      const projectConfig = {
753        arkObfuscator: {
754          filePathManager: {},
755          fileContentManager: fileContentManagerStub,
756        },
757      };
758      const previousStageSourceMap = {};
759
760      collectObfuscationFileContent(moduleInfo, projectConfig, previousStageSourceMap);
761
762      expect(fileContentManagerStub.updateFileContent.calledOnce).to.be.true;
763      expect(fileContentManagerStub.updateFileContent.calledWith({
764        moduleInfo: moduleInfo,
765        previousStageSourceMap: previousStageSourceMap,
766      })).to.be.true;
767    });
768
769    mocha.it('11-4: should call updateFileContent if the file is an original declaration file', function () {
770      const moduleInfo = {
771        buildFilePath: 'file.d.ts',
772        originSourceFilePath: 'file.d.ts',
773      };
774      const projectConfig = {
775        arkObfuscator: {
776          filePathManager: {},
777          fileContentManager: fileContentManagerStub,
778        },
779      };
780      const previousStageSourceMap = {};
781
782      collectObfuscationFileContent(moduleInfo, projectConfig, previousStageSourceMap);
783
784      expect(fileContentManagerStub.updateFileContent.calledOnce).to.be.true;
785      expect(fileContentManagerStub.updateFileContent.calledWith({
786        moduleInfo: moduleInfo,
787        previousStageSourceMap: previousStageSourceMap,
788      })).to.be.true;
789    });
790  });
791});