• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 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
17import { expect } from 'chai';
18import fs from "fs";
19import * as ts from 'typescript';
20import mocha from 'mocha';
21import path from "path";
22import sinon from 'sinon';
23
24import {
25  MergedConfig,
26  ObConfigResolver,
27  collectResevedFileNameInIDEConfig,
28  getNameCacheByPath,
29  getRelativeSourcePath,
30  handleKeepFilesAndGetDependencies,
31  setNewNameCache,
32  setUnobfuscationNames,
33  sourceFileDependencies,
34  writeObfuscatedFile,
35  writeObfuscationCaches,
36  IDENTIFIER_CACHE,
37  updateIncrementalCaches,
38  readProjectCaches,
39  getUpdatedFiles,
40  obfuscationPreprocess,
41  reObfuscate,
42  printObfLogger,
43  removeRedundantFiles
44} from '../../../lib/fast_build/ark_compiler/common/ob_config_resolver';
45import {
46  OBFUSCATION_RULE_PATH,
47  OBFUSCATION_RULE_TEMPLATE_PATH
48} from '../mock/rollup_mock/path_config';
49import { OBFUSCATION_TOOL } from '../../../lib/fast_build/ark_compiler/common/ark_define';
50import { RELEASE } from '../../../lib/fast_build/ark_compiler/common/ark_define';
51import RollUpPluginMock from '../mock/rollup_mock/rollup_plugin_mock';
52import {
53  ArkObfuscator,
54  nameCacheMap,
55  unobfuscationNamesObj,
56  ProjectCollections,
57  PerfMode,
58  TimeAndMemTimeTracker,
59  printerTimeAndMemDataConfig,
60} from 'arkguard';
61import * as arkUtils from '../../../lib/ark_utils'
62
63const OBFUSCATE_TESTDATA_DIR = path.resolve(__dirname, '../../../test/ark_compiler_ut/testdata/obfuscation');
64
65mocha.describe('test obfuscate config resolver api', function () {
66  mocha.before(function () {
67    this.rollup = new RollUpPluginMock();
68    let obfuscationContent = undefined;
69    try {
70      obfuscationContent = fs.readFileSync(OBFUSCATION_RULE_TEMPLATE_PATH, 'utf-8');
71      obfuscationContent = obfuscationContent.replace('OBFUSCATE_TESTDATA_DIR', OBFUSCATE_TESTDATA_DIR);
72      fs.writeFileSync(`${OBFUSCATION_RULE_PATH}`, obfuscationContent);
73    } catch (err) {
74      throw err;
75    }
76  });
77
78  mocha.afterEach(() => {
79    if (fs.existsSync(`${OBFUSCATION_RULE_PATH}`)) {
80      fs.unlinkSync(`${OBFUSCATION_RULE_PATH}`);
81    }
82  });
83
84  mocha.after(() => {
85    delete this.rollup;
86  });
87
88  mocha.it('1-1: test resolveDts', function () {
89    this.rollup.build(RELEASE);
90    const logger: object = this.rollup.share.getLogger(OBFUSCATION_TOOL);
91    this.rollup.share.projectConfig.obfuscationOptions = {
92      'selfConfig': {
93        'ruleOptions': {
94          'enable': true,
95          'rules': [ OBFUSCATION_RULE_PATH ]
96        },
97        'consumerRules': [],
98      },
99      'dependencies': {
100        'libraries': [],
101        'hars': []
102      }
103    };
104    const obConfig: ObConfigResolver =  new ObConfigResolver(this.rollup.share.projectConfig, logger, true);
105    const mergedObConfig: MergedConfig = obConfig.resolveObfuscationConfigs();
106    expect(mergedObConfig.options.enableToplevelObfuscation).to.be.true;
107    expect(mergedObConfig.options.enablePropertyObfuscation).to.be.false;
108
109    const reservedNames = mergedObConfig.reservedNames;
110    expect(reservedNames.length == 4).to.be.true;
111    expect(reservedNames.includes('matrix44')).to.be.true;
112    expect(reservedNames.includes('TranslateOption2')).to.be.true;
113    expect(reservedNames.includes('TestAdd')).to.be.true;
114    expect(reservedNames.includes('TestProperty')).to.be.true;
115
116    const reservedPropertyNames = mergedObConfig.reservedPropertyNames;
117    expect(reservedPropertyNames.length == 4).to.be.true;
118    expect(reservedPropertyNames.includes('matrix44')).to.be.true;
119    expect(reservedPropertyNames.includes('TranslateOption2')).to.be.true;
120    expect(reservedPropertyNames.includes('TestAdd')).to.be.true;
121    expect(reservedPropertyNames.includes('TestProperty')).to.be.true;
122
123    const reservedGlobalNames = mergedObConfig.reservedGlobalNames;
124    expect(reservedGlobalNames.length == 4).to.be.true;
125    expect(reservedGlobalNames.includes('matrix44')).to.be.true;
126    expect(reservedGlobalNames.includes('TranslateOption2')).to.be.true;
127    expect(reservedGlobalNames.includes('TestAdd')).to.be.true;
128    expect(reservedGlobalNames.includes('TestProperty')).to.be.true;
129
130    this.rollup.clearCache();
131  });
132
133  mocha.it('1-2: test resolveObfuscationConfigs: -enable-property-obfuscation', function () {
134    this.rollup.build(RELEASE);
135    const logger: object = this.rollup.share.getLogger(OBFUSCATION_TOOL);
136    const optionContent: string = '-enable-property-obfuscation';
137    fs.writeFileSync(`${OBFUSCATION_RULE_PATH}`, optionContent);
138    this.rollup.share.projectConfig.obfuscationOptions = {
139      'selfConfig': {
140        'ruleOptions': {
141          'enable': true,
142          'rules': [OBFUSCATION_RULE_PATH]
143        },
144        'consumerRules': [],
145      },
146      'dependencies': {
147        'libraries': [],
148        'hars': []
149      }
150    };
151    const obConfigResolver: ObConfigResolver =  new ObConfigResolver(this.rollup.share.projectConfig, logger, true);
152    const mergedObConfig: MergedConfig = obConfigResolver.resolveObfuscationConfigs();
153    const obOptions: ObOptions = mergedObConfig.options;
154    for (const [optionName, optionValue] of Object.entries(obOptions)) {
155      if (optionName === 'enablePropertyObfuscation') {
156        expect(optionValue).to.be.true;
157      } else {
158        if (typeof optionValue === 'boolean') {
159          expect(optionValue).to.be.false;
160        } else if (typeof optionValue === 'string') {
161          expect(optionValue === '').to.be.true;
162        }
163      }
164    }
165  });
166
167  mocha.it('1-3: test resolveObfuscationConfigs: -enable-property-obfuscation -enable-export-obfuscation', function () {
168    this.rollup.build(RELEASE);
169    const logger: object = this.rollup.share.getLogger(OBFUSCATION_TOOL);
170    const optionContent: string = '-enable-property-obfuscation\n-enable-export-obfuscation';
171    fs.writeFileSync(`${OBFUSCATION_RULE_PATH}`, optionContent);
172    this.rollup.share.projectConfig.obfuscationOptions = {
173      'selfConfig': {
174        'ruleOptions': {
175          'enable': true,
176          'rules': [OBFUSCATION_RULE_PATH]
177        },
178        'consumerRules': [],
179      },
180      'dependencies': {
181        'libraries': [],
182        'hars': []
183      }
184    };
185    const obConfigResolver: ObConfigResolver =  new ObConfigResolver(this.rollup.share.projectConfig, logger, true);
186    const mergedObConfig: MergedConfig = obConfigResolver.resolveObfuscationConfigs();
187    const obOptions: ObOptions = mergedObConfig.options;
188    for (const [optionName, optionValue] of Object.entries(obOptions)) {
189      if (optionName === 'enablePropertyObfuscation' || optionName === 'enableExportObfuscation') {
190        expect(optionValue).to.be.true;
191      } else {
192        if (typeof optionValue === 'boolean') {
193          expect(optionValue).to.be.false;
194        } else if (typeof optionValue === 'string') {
195          expect(optionValue === '').to.be.true;
196        }
197      }
198    }
199  });
200
201  mocha.it('1-3: test resolveObfuscationConfigs: -enable-property-obfuscation -enable-string-property-obfuscation', function () {
202    this.rollup.build(RELEASE);
203    const logger: object = this.rollup.share.getLogger(OBFUSCATION_TOOL);
204    const optionContent: string = '-enable-property-obfuscation\n-enable-string-property-obfuscation';
205    fs.writeFileSync(`${OBFUSCATION_RULE_PATH}`, optionContent);
206    this.rollup.share.projectConfig.obfuscationOptions = {
207      'selfConfig': {
208        'ruleOptions': {
209          'enable': true,
210          'rules': [OBFUSCATION_RULE_PATH]
211        },
212        'consumerRules': [],
213      },
214      'dependencies': {
215        'libraries': [],
216        'hars': []
217      }
218    };
219    const obConfigResolver: ObConfigResolver =  new ObConfigResolver(this.rollup.share.projectConfig, logger, true);
220    const mergedObConfig: MergedConfig = obConfigResolver.resolveObfuscationConfigs();
221    const obOptions: ObOptions = mergedObConfig.options;
222    for (const [optionName, optionValue] of Object.entries(obOptions)) {
223      if (optionName === 'enablePropertyObfuscation' || optionName === 'enableStringPropertyObfuscation') {
224        expect(optionValue).to.be.true;
225      } else {
226        if (typeof optionValue === 'boolean') {
227          expect(optionValue).to.be.false;
228        } else if (typeof optionValue === 'string') {
229          expect(optionValue === '').to.be.true;
230        }
231      }
232    }
233  });
234
235  mocha.it('1-4: test resolveObfuscationConfigs: -enable-property-obfuscation -enable-toplevel-obfuscation', function () {
236    this.rollup.build(RELEASE);
237    const logger: object = this.rollup.share.getLogger(OBFUSCATION_TOOL);
238    const optionContent: string = '-enable-property-obfuscation\n-enable-toplevel-obfuscation';
239    fs.writeFileSync(`${OBFUSCATION_RULE_PATH}`, optionContent);
240    this.rollup.share.projectConfig.obfuscationOptions = {
241      'selfConfig': {
242        'ruleOptions': {
243          'enable': true,
244          'rules': [OBFUSCATION_RULE_PATH]
245        },
246        'consumerRules': [],
247      },
248      'dependencies': {
249        'libraries': [],
250        'hars': []
251      }
252    };
253    const obConfigResolver: ObConfigResolver =  new ObConfigResolver(this.rollup.share.projectConfig, logger, true);
254    const mergedObConfig: MergedConfig = obConfigResolver.resolveObfuscationConfigs();
255    const obOptions: ObOptions = mergedObConfig.options;
256    for (const [optionName, optionValue] of Object.entries(obOptions)) {
257      if (optionName === 'enablePropertyObfuscation' || optionName === 'enableToplevelObfuscation') {
258        expect(optionValue).to.be.true;
259      } else {
260        if (typeof optionValue === 'boolean') {
261          expect(optionValue).to.be.false;
262        } else if (typeof optionValue === 'string') {
263          expect(optionValue === '').to.be.true;
264        }
265      }
266    }
267  });
268
269  mocha.it('1-5: test resolveObfuscationConfigs: enable all', function () {
270    this.rollup.build(RELEASE);
271    const logger: object = this.rollup.share.getLogger(OBFUSCATION_TOOL);
272    const optionContent: string = '-enable-property-obfuscation\n-enable-export-obfuscation\n-enable-filename-obfuscation\n'
273                                + '-enable-string-property-obfuscation\n-enable-toplevel-obfuscation';
274    fs.writeFileSync(`${OBFUSCATION_RULE_PATH}`, optionContent);
275    this.rollup.share.projectConfig.obfuscationOptions = {
276      'selfConfig': {
277        'ruleOptions': {
278          'enable': true,
279          'rules': [OBFUSCATION_RULE_PATH]
280        },
281        'consumerRules': [],
282      },
283      'dependencies': {
284        'libraries': [],
285        'hars': []
286      }
287    };
288    const obConfigResolver: ObConfigResolver =  new ObConfigResolver(this.rollup.share.projectConfig, logger, true);
289    const mergedObConfig: MergedConfig = obConfigResolver.resolveObfuscationConfigs();
290    const obOptions: ObOptions = mergedObConfig.options;
291    expect(obOptions.disableObfuscation).to.be.false;
292    expect(obOptions.enablePropertyObfuscation).to.be.true;
293    expect(obOptions.enableStringPropertyObfuscation).to.be.true;
294    expect(obOptions.enableToplevelObfuscation).to.be.true;
295    expect(obOptions.enableFileNameObfuscation).to.be.true;
296    expect(obOptions.enableExportObfuscation).to.be.true;
297    expect(obOptions.removeComments).to.be.false;
298    expect(obOptions.compact).to.be.false;
299    expect(obOptions.removeLog).to.be.false;
300  });
301
302  describe('2: test collectResevedFileNameInIDEConfig', function() {
303    let aceModuleJsonPath = '';
304    let ohPackagePath = '';
305    let projectConfig = {};
306    let modulePathMap = {};
307    let entryArray = [];
308    mocha.before('init config', function () {
309      aceModuleJsonPath = path.join(OBFUSCATE_TESTDATA_DIR, 'filename_obf/module.json');
310      ohPackagePath = path.join(OBFUSCATE_TESTDATA_DIR, 'filename_obf/oh-package.json5');
311      projectConfig = {
312        aceModuleJsonPath: aceModuleJsonPath,
313        projectPath: '/mnt/application/entry/src/main/ets',
314        cachePath: '/mnt/application/entry/build/default/cache/default/default@HarCompileArkTs/esmodules/release',
315        aceModuleBuild: '/mnt/application/entry/build/default/intermediates/loader_out',
316        compileShared: false,
317        compileHar: false,
318        byteCodeHar: false,
319      };
320      modulePathMap = {
321        'entry': '/mnt/application/entry',
322        'harpackagename': '/mnt/application/harPackageName'
323      };
324      entryArray = [
325        'entryability/EntryAbility',
326        'pages/Index'
327      ];
328    });
329
330    mocha.it('2-1: test collectResevedFileNameInIDEConfig in hsp module', function () {
331      projectConfig.compileShared = true;
332      projectConfig.compileHar = false;
333      projectConfig.byteCodeHar = false;
334      const acutualReservedFileNames: string[] = collectResevedFileNameInIDEConfig(ohPackagePath, projectConfig, modulePathMap, entryArray);
335      const expectReservedFileNames = [
336        'entryability',
337        'EntryAbility',
338        'pages',
339        'Index',
340        '',
341        'mnt',
342        'application',
343        'entry',
344        '',
345        'mnt',
346        'application',
347        'harPackageName',
348        'entry',
349        'harpackagename',
350        '.',
351        'Index-oh-package.ets',
352        '.',
353        'Type-oh-package.ets',
354        '..',
355        '..',
356        'Index2.ets',
357        '',
358        'mnt',
359        'application',
360        'entry',
361        'build',
362        'default',
363        'intermediates',
364        'loader_out',
365        'etsFortgz',
366        '',
367        'mnt',
368        'application',
369        'entry',
370        'src',
371        'main',
372        'ets',
373        '',
374        'mnt',
375        'application',
376        'entry',
377        'build',
378        'default',
379        'cache',
380        'default',
381        'default@HarCompileArkTs',
382        'esmodules',
383        'release'
384      ];
385      expect(acutualReservedFileNames.toString() === expectReservedFileNames.toString()).to.be.true;
386    });
387
388    mocha.it('2-2: test collectResevedFileNameInIDEConfig in hap module', function () {
389      projectConfig.compileShared = false;
390      projectConfig.compileHar = false;
391      projectConfig.byteCodeHar = false;
392      const acutualReservedFileNames: string[] = collectResevedFileNameInIDEConfig(ohPackagePath, projectConfig, modulePathMap, entryArray);
393      const expectReservedFileNames = [
394        'entryability',
395        'EntryAbility',
396        'pages',
397        'Index',
398        '',
399        'mnt',
400        'application',
401        'entry',
402        '',
403        'mnt',
404        'application',
405        'harPackageName',
406        'entry',
407        'harpackagename',
408        '.',
409        'Index-oh-package.ets',
410        '.',
411        'Type-oh-package.ets',
412        '..',
413        '..',
414        'Index2.ets',
415        '',
416        'mnt',
417        'application',
418        'entry',
419        'src',
420        'main',
421        'ets',
422        '',
423        'mnt',
424        'application',
425        'entry',
426        'build',
427        'default',
428        'cache',
429        'default',
430        'default@HarCompileArkTs',
431        'esmodules',
432        'release'
433      ];
434      expect(acutualReservedFileNames.toString() === expectReservedFileNames.toString()).to.be.true;
435    });
436
437    mocha.it('2-3: test collectResevedFileNameInIDEConfig in source har module', function () {
438      projectConfig.compileShared = false;
439      projectConfig.compileHar = true;
440      projectConfig.byteCodeHar = false;
441      const acutualReservedFileNames: string[] = collectResevedFileNameInIDEConfig(ohPackagePath, projectConfig, modulePathMap, entryArray);
442      const expectReservedFileNames = [
443        'entryability',
444        'EntryAbility',
445        'pages',
446        'Index',
447        '',
448        'mnt',
449        'application',
450        'entry',
451        '',
452        'mnt',
453        'application',
454        'harPackageName',
455        'entry',
456        'harpackagename',
457        '.',
458        'Index-oh-package.ets',
459        '.',
460        'Type-oh-package.ets',
461        '..',
462        '..',
463        'Index2.ets',
464        '',
465        'mnt',
466        'application',
467        'entry',
468        'src',
469        'main',
470        'ets',
471        '',
472        'mnt',
473        'application',
474        'entry',
475        'build',
476        'default',
477        'cache',
478        'default',
479        'default@HarCompileArkTs',
480        'esmodules',
481        'release'
482      ];
483      expect(acutualReservedFileNames.toString() === expectReservedFileNames.toString()).to.be.true;
484    });
485
486    mocha.it('2-4: test collectResevedFileNameInIDEConfig in byte code har module', function () {
487      projectConfig.compileShared = false;
488      projectConfig.compileHar = true;
489      projectConfig.byteCodeHar = true;
490      const acutualReservedFileNames: string[] = collectResevedFileNameInIDEConfig(ohPackagePath, projectConfig, modulePathMap, entryArray);
491      const expectReservedFileNames = [
492        'entryability',
493        'EntryAbility',
494        'pages',
495        'Index',
496        '',
497        'mnt',
498        'application',
499        'entry',
500        '',
501        'mnt',
502        'application',
503        'harPackageName',
504        'entry',
505        'harpackagename',
506        '.',
507        'Index-oh-package.ets',
508        '.',
509        'Type-oh-package.ets',
510        '..',
511        '..',
512        'Index2.ets',
513        '',
514        'mnt',
515        'application',
516        'entry',
517        'build',
518        'default',
519        'intermediates',
520        'loader_out',
521        'etsFortgz',
522        '',
523        'mnt',
524        'application',
525        'entry',
526        'src',
527        'main',
528        'ets',
529        '',
530        'mnt',
531        'application',
532        'entry',
533        'build',
534        'default',
535        'cache',
536        'default',
537        'default@HarCompileArkTs',
538        'esmodules',
539        'release'
540      ];
541      expect(acutualReservedFileNames.toString() === expectReservedFileNames.toString()).to.be.true;
542    });
543  })
544
545  mocha.it('4-1: test getRelativeSourcePath: filePath starts with projectRootPath', function () {
546    const filePath = 'C:/projects/my-project/src/file.ts';
547    const projectRootPath = 'C:/projects/my-project';
548    const belongProjectPath = undefined;
549    const relativePath = getRelativeSourcePath(filePath, projectRootPath, belongProjectPath);
550    expect(relativePath).to.equal('src/file.ts');
551  });
552
553  mocha.it('4-2: test getRelativeSourcePath: filePath starts with belongProjectPath', function () {
554    const filePath = 'C:/projects/another-project/src/file.ts';
555    const projectRootPath = 'C:/projects/my-project';
556    const belongProjectPath = 'C:/projects/another-project';
557    const relativePath = getRelativeSourcePath(filePath, projectRootPath, belongProjectPath);
558    expect(relativePath).to.equal('src/file.ts');
559  });
560
561  mocha.it('4-3: test getRelativeSourcePath: undefined projectRootPath', function () {
562    const filePath = 'C:/projects/another-project/src/file.ts';
563    const projectRootPath = undefined;
564    const belongProjectPath = 'C:/projects/another-project';
565    const relativePath = getRelativeSourcePath(filePath, projectRootPath, belongProjectPath);
566    expect(relativePath).to.equal('src/file.ts');
567  });
568
569  mocha.it('4-4: test getRelativeSourcePath: undefined belongProjectPath ', function () {
570    const filePath = 'C:/projects/my-project/src/file.ts';
571    const projectRootPath = 'C:/projects/my-project';
572    const belongProjectPath = undefined;
573    const relativePath = getRelativeSourcePath(filePath, projectRootPath, belongProjectPath);
574    expect(relativePath).to.equal('src/file.ts');
575  });
576
577  mocha.it('5-1: test getFileNamesForScanningWhitelist: -keep is empty ', function () {
578    this.rollup.build(RELEASE);
579    const logger: object = this.rollup.share.getLogger(OBFUSCATION_TOOL);
580    const optionContent: string = '';
581    fs.writeFileSync(`${OBFUSCATION_RULE_PATH}`, optionContent);
582    this.rollup.share.projectConfig.projectRootPath = ''
583    this.rollup.share.projectConfig.obfuscationOptions = {
584      'selfConfig': {
585        'ruleOptions': {
586          'enable': true,
587          'rules': [OBFUSCATION_RULE_PATH]
588        },
589        'consumerRules': [],
590      },
591      'dependencies': {
592        'libraries': [],
593        'hars': []
594      }
595    };
596    const obConfigResolver: ObConfigResolver =  new ObConfigResolver(this.rollup.share.projectConfig, logger, true);
597    const mergedObConfig: MergedConfig = obConfigResolver.resolveObfuscationConfigs();
598    mergedObConfig.keepSourceOfPaths = [];
599    const keepFilesAndDependencies: Set<string> = handleKeepFilesAndGetDependencies(mergedObConfig,
600      this.rollup.share.projectConfig.projectRootPath, new ArkObfuscator());
601    expect(keepFilesAndDependencies.size === 0).to.be.true;
602  });
603
604  mocha.it('5-2: test getFileNamesForScanningWhitelist: unable export obfuscation ', function () {
605    this.rollup.build(RELEASE);
606    const logger: object = this.rollup.share.getLogger(OBFUSCATION_TOOL);
607    const optionContent: string = '-enble-export-obfuscation';
608    fs.writeFileSync(`${OBFUSCATION_RULE_PATH}`, optionContent);
609    this.rollup.share.projectConfig.projectRootPath = ''
610    this.rollup.share.projectConfig.obfuscationOptions = {
611      'selfConfig': {
612        'ruleOptions': {
613          'enable': true,
614          'rules': [OBFUSCATION_RULE_PATH]
615        },
616        'consumerRules': [],
617      },
618      'dependencies': {
619        'libraries': [],
620        'hars': []
621      }
622    };
623
624    const obConfigResolver: ObConfigResolver =  new ObConfigResolver(this.rollup.share.projectConfig, logger, true);
625    const mergedObConfig: MergedConfig = obConfigResolver.resolveObfuscationConfigs();
626
627    let testFile1: string = path.resolve(__dirname, '../testdata/obfuscation_keeptest/project1/file1.js');
628    let testFile2: string = path.resolve(__dirname, '../testdata/obfuscation_keeptest/project1/file2.js');
629    let testFile3: string = path.resolve(__dirname, '../testdata/obfuscation_keeptest/project2/file3.js');
630    let testFile4: string = path.resolve(__dirname, '../testdata/obfuscation_keeptest/project2/file4.js');
631    let testFile5: string = path.resolve(__dirname, '../testdata/obfuscation_keeptest/project3/file5.js');
632
633    mergedObConfig.keepSourceOfPaths = [
634      testFile1,
635      testFile3
636    ];
637    mergedObConfig.excludePathSet = new Set<string>([]);
638    mergedObConfig.options.enableExportObfuscation = true;
639    this.rollup.share.projectConfig.rootPathSet = new Set<string>([
640      path.resolve(__dirname, '../testdata/obfuscation_keeptest/project1/'),
641      path.resolve(__dirname, '../testdata/obfuscation_keeptest/project2/')
642    ]);
643    this.rollup.share.projectConfig.projectRootPath = path.resolve(__dirname, '../testdata/obfuscation_keeptest/project1/');
644
645    const cache1: ts.ModeAwareCache<ts.ResolvedModuleFull | undefined> =
646      ts.createModeAwareCache<ts.ResolvedModuleFull | undefined>();
647    cache1.set('file1.ts', ts.ModuleKind.ESNext, {
648      resolvedFileName: testFile2,
649      isExternalLibraryImport: false,
650      extension: ts.Extension.Js
651    });
652    cache1.set('file2.ts', ts.ModuleKind.ESNext, {
653      resolvedFileName: testFile3,
654      isExternalLibraryImport: false,
655      extension: ts.Extension.Js
656    });
657    sourceFileDependencies.set(testFile1, cache1);
658
659    const cache2: ts.ModeAwareCache<ts.ResolvedModuleFull | undefined> =
660      ts.createModeAwareCache<ts.ResolvedModuleFull | undefined>();
661    cache2.set('file4.ts', ts.ModuleKind.ESNext, {
662      resolvedFileName: testFile4,
663      isExternalLibraryImport: false,
664      extension: ts.Extension.Js
665    });
666    cache2.set('file5.ts', ts.ModuleKind.ESNext, {
667      resolvedFileName: testFile5,
668      isExternalLibraryImport: false,
669      extension: ts.Extension.Js
670    });
671    sourceFileDependencies.set(testFile3, cache2);
672
673    let arkguardConfig: Object = {
674      mNameObfuscation: {
675        mEnable: true,
676        mNameGeneratorType: 1,
677        mRenameProperties: false,
678        mReservedProperties: [],
679        mTopLevel: false,
680        mReservedToplevelNames:[],
681      },
682      mKeepFileSourceCode: {
683        mKeepSourceOfPaths: [
684          testFile1,
685          testFile3
686        ],
687        mkeepFilesAndDependencies: []
688      },
689      mExportObfuscation: true,
690      mPerformancePrinter: []
691    };
692
693    let arkObfuscator: ArkObfuscator = new ArkObfuscator();
694    arkObfuscator.init(arkguardConfig);
695
696    const keepFilesAndDependencies: Set<string> = handleKeepFilesAndGetDependencies(mergedObConfig,
697      arkObfuscator, this.rollup.share.projectConfig);
698    expect(keepFilesAndDependencies.has(testFile1)).to.be.true;
699    expect(keepFilesAndDependencies.has(testFile2)).to.be.true;
700    expect(keepFilesAndDependencies.has(testFile3)).to.be.true;
701    expect(keepFilesAndDependencies.has(testFile4)).to.be.true;
702    expect(keepFilesAndDependencies.has(testFile5)).to.be.false;
703  });
704
705  mocha.it('6-1: test getHistoryNameCache: isDeclaration false', function () {
706    const moduleInfo = {
707      content: 'module content',
708      buildFilePath: 'build/path/to/file.ts',
709      relativeSourceFilePath: 'src/file.ts',
710      originSourceFilePath: 'C:/projects/my-project/src/file.ts'
711    };
712    nameCacheMap.set('src/file.ts', {
713      [IDENTIFIER_CACHE]: {
714        'identifier1:1': 'obfuscated1',
715        identifier2: 'obfuscated2'
716      }
717    });
718    const isDeclaration: boolean = false;
719    const projectRootPath: string = 'C:/projects/my-project';
720    const result: Map<string, string> = getNameCacheByPath(moduleInfo, isDeclaration, projectRootPath);
721    nameCacheMap.clear();
722    expect(result.size).to.equal(2);
723    expect(result.get('identifier1')).to.equal('obfuscated1');
724    expect(result.get('identifier2')).to.equal('obfuscated2');
725  });
726
727  mocha.it('6-2: test getHistoryNameCache: isDeclaration true', function () {
728    const moduleInfo = {
729      content: 'module content',
730      buildFilePath: 'build/path/to/file.d.ts',
731      relativeSourceFilePath: 'src/file.ts',
732      originSourceFilePath: 'C:/projects/my-project/src/file.ts'
733    };
734    nameCacheMap.set('src/file.ts', {
735      [IDENTIFIER_CACHE]: {
736        'identifier1:1': 'obfuscated1',
737        identifier2: 'obfuscated2'
738      }
739    });
740    const isDeclaration: boolean = true;
741    const projectRootPath: string = 'C:/projects/my-project';
742    const result: Map<string, string> = getNameCacheByPath(moduleInfo, isDeclaration, projectRootPath);
743    nameCacheMap.clear();
744    expect(result.size).to.equal(2);
745    expect(result.get('identifier1')).to.equal('obfuscated1');
746    expect(result.get('identifier2')).to.equal('obfuscated2');
747  });
748
749  mocha.it('7-1: test setNewNameCache: isOhModule is false', function () {
750    const moduleInfo = {
751      content: 'module content',
752      buildFilePath: 'build/path/to/file.ts',
753      relativeSourceFilePath: 'src/file.ts',
754      originSourceFilePath: 'C:/projects/my-project/src/file.ts'
755    };
756    nameCacheMap.set('src/file.ts', {
757      [IDENTIFIER_CACHE]: {
758        'identifier1:1': 'obfuscated1',
759        identifier2: 'obfuscated2'
760      }
761    });
762    const newNameCache = {
763      [IDENTIFIER_CACHE]: {
764        'identifier3:3': 'obfuscated3'
765      }
766    };
767    const isDeclaration: boolean = false;
768    const projectConfig: Object = {
769      obfuscationMergedObConfig: { options: { enableFileNameObfuscation: true } },
770      projectRootPath: '/projectRoot',
771      packageDir: 'oh_modules',
772      modulePathMap: {
773        module1: '/externalModule'
774      },
775    };
776    setNewNameCache(newNameCache, isDeclaration, moduleInfo, projectConfig);
777    const result: string | {} = nameCacheMap.get(moduleInfo.relativeSourceFilePath);
778    nameCacheMap.clear();
779
780    expect(result[IDENTIFIER_CACHE]['identifier3:3'] === 'obfuscated3').to.be.true;
781    expect(result.obfName === 'src/file.ts').to.be.false;
782  });
783
784  mocha.it('7-2: test setNewNameCache: isOhModule is true', function () {
785    const moduleInfo = {
786      content: 'module content',
787      buildFilePath: 'build/path/to/file.ts',
788      relativeSourceFilePath: 'src/file.ts',
789      originSourceFilePath: '/projectRoot/oh_modules/src/file.ts'
790    };
791    nameCacheMap.set('src/file.ts', {
792      [IDENTIFIER_CACHE]: {
793        'identifier1:1': 'obfuscated1',
794        identifier2: 'obfuscated2'
795      }
796    });
797    const newNameCache = {
798      [IDENTIFIER_CACHE]: {
799        'identifier3:3': 'obfuscated3'
800      }
801    };
802    const isDeclaration: boolean = false;
803    const projectConfig: Object = {
804      obfuscationMergedObConfig: { options: { enableFileNameObfuscation: true } },
805      projectRootPath: '/projectRoot',
806      packageDir: 'oh_modules'
807    };
808    setNewNameCache(newNameCache, isDeclaration, moduleInfo, projectConfig);
809    const result: string | {} = nameCacheMap.get(moduleInfo.relativeSourceFilePath);
810    nameCacheMap.clear();
811
812    expect(result[IDENTIFIER_CACHE]['identifier3:3'] === 'obfuscated3').to.be.true;
813    expect(result.obfName === 'src/file.ts').to.be.true;
814  });
815
816  mocha.it('8-1: test setUnobfuscationNames', function () {
817    const relativeSourceFilePath: string = 'src/file.ts';
818    const unobfuscationNameMap: Map<string, Set<string>> = new Map([
819      ['key1', new Set(['value1', 'value2'])],
820      ['key2', new Set(['value3'])]
821    ]);
822    const isDeclaration: boolean = false;
823
824    setUnobfuscationNames(unobfuscationNameMap, relativeSourceFilePath, isDeclaration);
825
826    expect(unobfuscationNamesObj[relativeSourceFilePath]).to.deep.equal({
827      key1: ['value1', 'value2'],
828      key2: ['value3']
829    });
830  });
831
832  mocha.it('9-1: test writeFile', function () {
833    const newFilePath: string = '../../test/ark_compiler_ut/testdata/writeFile.ts';
834    const content: string = 'obfuscated code';
835
836    writeObfuscatedFile(newFilePath, content);
837
838    expect(fs.existsSync(newFilePath)).to.be.true;
839    const fileContent: string = fs.readFileSync(newFilePath, 'utf-8');
840    expect(fileContent).to.equal(content);
841    fs.unlinkSync(newFilePath);
842  });
843
844  mocha.describe('10: test Obfuscation Functions', function () {
845    let arkObfuscatorStub;
846    let filePathManagerStub;
847    let fileContentManagerStub;
848    let projectWhiteListManagerStub;
849    let obfConfigResolverStub;
850
851    mocha.beforeEach(function () {
852      obfConfigResolverStub = {
853        emitConsumerConfigFiles: sinon.stub(),
854      };
855      filePathManagerStub = {
856        getDeletedSourceFilePaths: sinon.stub(),
857        createOrUpdateSourceFilePaths: sinon.stub(),
858        addedSourceFilePaths: new Set(),
859      };
860      fileContentManagerStub = {
861        deleteFileContent: sinon.stub(),
862        readFileNamesMap: sinon.stub(),
863        getSortedFiles: sinon.stub(),
864        fileNamesMap: new Map(),
865        readFileContent: sinon.stub(),
866      };
867      projectWhiteListManagerStub = {
868        createOrUpdateWhiteListCaches: sinon.stub(),
869        getShouldReObfuscate: sinon.stub(),
870      };
871      arkObfuscatorStub = {
872        filePathManager: filePathManagerStub,
873        fileContentManager: fileContentManagerStub,
874        shouldReObfuscate: false,
875        isIncremental: false,
876        obfConfigResolver: obfConfigResolverStub,
877      };
878      ProjectCollections.initProjectWhiteListManager('', false, false);
879      sinon.stub(ProjectCollections, 'projectWhiteListManager').value(projectWhiteListManagerStub);
880    });
881
882    mocha.afterEach(function () {
883      sinon.restore();
884    });
885
886    mocha.describe('10-1: updateIncrementalCaches', function () {
887      mocha.it('10-1-1: should update caches and set shouldReObfuscate flag if needed', function () {
888        const deletedFilesSet = new Set(['file1.ts', 'file2.ts']);
889        filePathManagerStub.getDeletedSourceFilePaths.returns(deletedFilesSet);
890        projectWhiteListManagerStub.getShouldReObfuscate.returns(true);
891
892        updateIncrementalCaches(arkObfuscatorStub);
893
894        expect(projectWhiteListManagerStub.createOrUpdateWhiteListCaches.calledWith(deletedFilesSet)).to.be.true;
895        expect(fileContentManagerStub.deleteFileContent.calledWith(deletedFilesSet)).to.be.true;
896        expect(arkObfuscatorStub.shouldReObfuscate).to.be.true;
897      });
898
899      mocha.it('10-1-2: should not set shouldReObfuscate flag if not needed', function () {
900        const deletedFilesSet = new Set(['file1.ts', 'file2.ts']);
901        filePathManagerStub.getDeletedSourceFilePaths.returns(deletedFilesSet);
902        projectWhiteListManagerStub.getShouldReObfuscate.returns(false);
903
904        updateIncrementalCaches(arkObfuscatorStub);
905
906        expect(arkObfuscatorStub.shouldReObfuscate).to.be.false;
907      });
908    });
909
910    mocha.describe('10-2: readProjectCaches', function () {
911      mocha.it('10-2-1: should update source file paths and read file names map if incremental', function () {
912        const allFiles = new Set(['file1.ts', 'file2.ts']);
913        arkObfuscatorStub.isIncremental = true;
914
915        readProjectCaches(allFiles, arkObfuscatorStub);
916
917        expect(filePathManagerStub.createOrUpdateSourceFilePaths.calledWith(allFiles)).to.be.true;
918        expect(fileContentManagerStub.readFileNamesMap.calledOnce).to.be.true;
919      });
920
921      mocha.it('10-2-2: should not read file names map if not incremental', function () {
922        const allFiles = new Set(['file1.ts', 'file2.ts']);
923        arkObfuscatorStub.isIncremental = false;
924
925        readProjectCaches(allFiles, arkObfuscatorStub);
926
927        expect(fileContentManagerStub.readFileNamesMap.called).to.be.false;
928      });
929    });
930
931    mocha.describe('10-3: getUpdatedFiles', function () {
932      mocha.it('10-3-1: should return updated files if incremental', function () {
933        const sourceProjectConfig = {
934          arkObfuscator: {
935            isIncremental: true,
936            filePathManager: {
937              addedSourceFilePaths: new Set(['file3.ts']),
938            },
939          },
940        };
941        const allSourceFilePaths = new Set(['file1.ts', 'file2.ts', 'file3.d.ts', 'file4.d.ets']);
942        const moduleSourceFiles = [{ moduleId: 'file1.ts' }, { moduleId: 'file2.ts' }];
943        const updatedFiles = getUpdatedFiles(sourceProjectConfig, allSourceFilePaths, moduleSourceFiles);
944        expect(updatedFiles).to.deep.equal(new Set(['file1.ts', 'file2.ts', 'file3.ts', 'file3.d.ts', 'file4.d.ets']));
945      });
946
947      mocha.it('10-3-2: should return all source files if not incremental', function () {
948        const sourceProjectConfig = {
949          arkObfuscator: {
950            isIncremental: false,
951          },
952        };
953        const allSourceFilePaths = new Set(['file1.ts', 'file2.ts', 'file3.d.ts']);
954        const moduleSourceFiles = [{ moduleId: 'file1.ts' }, { moduleId: 'file2.ts' }];
955        const updatedFiles = getUpdatedFiles(sourceProjectConfig, allSourceFilePaths, moduleSourceFiles);
956        expect(updatedFiles).to.deep.equal(allSourceFilePaths);
957      });
958    });
959
960    mocha.describe('10-4: obfuscationPreprocess', function () {
961      mocha.it('10-4-1: should call readProjectCaches and updateIncrementalCaches if arkObfuscator exists', function () {
962        const sourceProjectConfig = {
963          arkObfuscator: arkObfuscatorStub,
964        };
965        const allSourceFilePaths = new Set(['file1.ts', 'file2.ts']);
966        const obfuscationConfig = {};
967        const keepFilesAndDependencies = new Set();
968        const moduleSourceFiles = [{ moduleId: 'file1.ts' }, { moduleId: 'file2.ts' }];
969
970        obfuscationPreprocess(
971          sourceProjectConfig,
972          obfuscationConfig,
973          allSourceFilePaths,
974          keepFilesAndDependencies,
975          moduleSourceFiles
976        );
977
978        expect(filePathManagerStub.createOrUpdateSourceFilePaths.calledWith(allSourceFilePaths)).to.be.true;
979        expect(projectWhiteListManagerStub.createOrUpdateWhiteListCaches.called).to.be.true;
980        expect(arkObfuscatorStub.obfConfigResolver.emitConsumerConfigFiles.called).to.be.true;
981        expect(ProjectCollections.projectWhiteListManager).to.be.undefined;
982      });
983
984      mocha.it('10-4-2: should not call readProjectCaches if arkObfuscator does not exist', function () {
985        const sourceProjectConfig = {};
986        const allSourceFilePaths = new Set(['file1.ts', 'file2.ts']);
987        const obfuscationConfig = {};
988        const keepFilesAndDependencies = new Set();
989        const moduleSourceFiles = [{ moduleId: 'file1.ts' }, { moduleId: 'file2.ts' }];
990
991        obfuscationPreprocess(
992          sourceProjectConfig,
993          obfuscationConfig,
994          allSourceFilePaths,
995          keepFilesAndDependencies,
996          moduleSourceFiles
997        );
998
999        expect(filePathManagerStub.createOrUpdateSourceFilePaths.called).to.be.false;
1000      });
1001    });
1002
1003    mocha.describe('10-5: reObfuscate', function () {
1004      mocha.it('10-5-1: should update harFilesRecord if is declaration file', async function () {
1005        const harFilesRecord = new Map();
1006        const logger = {};
1007        const projectConfig = {};
1008        const sortedFiles = ['file1.d.ts', 'file2.d.ts'];
1009        const fileContentObj1 = {
1010          moduleInfo: {
1011            originSourceFilePath: 'file1.d.ts',
1012            buildFilePath: 'file1.d.ts',
1013            content: 'content1',
1014          },
1015          previousStageSourceMap: {},
1016        };
1017        const fileContentObj2 = {
1018          moduleInfo: {
1019            originSourceFilePath: 'file2.d.ts',
1020            buildFilePath: 'file2.d.ts',
1021            content: 'content2',
1022          },
1023          previousStageSourceMap: {},
1024        };
1025        fileContentManagerStub.getSortedFiles.returns(sortedFiles);
1026        fileContentManagerStub.fileNamesMap.set('file1.d.ts', 'file1.d.ts');
1027        fileContentManagerStub.fileNamesMap.set('file2.d.ts', 'file2.d.ts');
1028        fileContentManagerStub.readFileContent
1029          .withArgs('file1.d.ts').returns(fileContentObj1)
1030          .withArgs('file2.d.ts').returns(fileContentObj2);
1031        harFilesRecord.set('file2.d.ts',{});
1032        await reObfuscate(arkObfuscatorStub, harFilesRecord, printObfLogger, projectConfig);
1033        expect(harFilesRecord.has('file1.d.ts')).to.be.true;
1034        expect(harFilesRecord.get('file1.d.ts')).to.deep.equal({
1035          sourcePath: 'file1.d.ts',
1036          originalDeclarationCachePath: 'file1.d.ts',
1037          originalDeclarationContent: 'content1'
1038        });
1039        expect(harFilesRecord.has('file2.d.ts')).to.be.true;
1040        expect(harFilesRecord.get('file2.d.ts')).to.deep.equal({});
1041      });
1042
1043      mocha.it('10-5-2: should writeArkguardObfuscatedSourceCode if is not declaraiont file', async function () {
1044        const harFilesRecord = new Map();
1045        const logger = {};
1046        const projectConfig = {};
1047        const sortedFiles = ['file1.ts', 'file2.ts'];
1048        const fileContentObj1 = {
1049          moduleInfo: {
1050            originSourceFilePath: 'file1.ts',
1051            buildFilePath: 'file1.ts',
1052            content: 'content1',
1053          },
1054          previousStageSourceMap: {},
1055        };
1056        const fileContentObj2 = {
1057          moduleInfo: {
1058            originSourceFilePath: 'file2.ts',
1059            buildFilePath: 'file2.ts',
1060            content: 'content2',
1061          },
1062          previousStageSourceMap: {},
1063        };
1064        let writeArkguardObfuscatedSourceCodeStub = sinon.stub(arkUtils, 'writeArkguardObfuscatedSourceCode');
1065        fileContentManagerStub.getSortedFiles.returns(sortedFiles);
1066        fileContentManagerStub.fileNamesMap.set('file1.ts', 'file1.ts');
1067        fileContentManagerStub.fileNamesMap.set('file2.ts', 'file2.ts');
1068        fileContentManagerStub.readFileContent
1069          .withArgs('file1.ts').returns(fileContentObj1)
1070          .withArgs('file2.ts').returns(fileContentObj2);
1071        await reObfuscate(arkObfuscatorStub, harFilesRecord, printObfLogger, projectConfig);
1072        expect(writeArkguardObfuscatedSourceCodeStub.calledTwice).to.be.true;
1073      });
1074    });
1075
1076    mocha.describe('10-6: writeObfuscationCaches', function () {
1077      let testCacheDir: string = '';
1078      let timePerformanceFilePath: string = '';
1079      let memoryPerformanceFilePath: string = '';
1080
1081      mocha.beforeEach(function () {
1082        printerTimeAndMemDataConfig.mTimeAndMemPrinter = true;
1083        testCacheDir = '../../test/ark_compiler_ut/testdata/';
1084        TimeAndMemTimeTracker.obfuscationCacheDir = testCacheDir;
1085        timePerformanceFilePath = path.join(testCacheDir, 'timePerformanceData.json');
1086        memoryPerformanceFilePath = path.join(testCacheDir, 'memoryPerformanceData.json');
1087        if (!fs.existsSync(testCacheDir)) {
1088          fs.mkdirSync(testCacheDir, { recursive: true });
1089        }
1090      });
1091
1092      mocha.afterEach(function () {
1093        if (fs.existsSync(timePerformanceFilePath)) {
1094          fs.unlinkSync(timePerformanceFilePath);
1095        }
1096        if (fs.existsSync(memoryPerformanceFilePath)) {
1097          fs.unlinkSync(memoryPerformanceFilePath);
1098        }
1099        if (fs.existsSync(testCacheDir)) {
1100          fs.rmdirSync(testCacheDir, { recursive: true });
1101        }
1102      });
1103
1104      mocha.it('10-6-1: should call enableTimeAndMemoryPrint when perf is ADVANCED', async function () {
1105        this.rollup.share.projectConfig.perf = PerfMode.ADVANCED;
1106        const sourceProjectConfig = Object.assign(this.rollup.share.arkProjectConfig, this.rollup.share.projectConfig);
1107        await writeObfuscationCaches(sourceProjectConfig, undefined);
1108        await new Promise(resolve => setTimeout(resolve, 100));
1109        expect(fs.existsSync(timePerformanceFilePath)).to.be.true;
1110        expect(fs.existsSync(memoryPerformanceFilePath)).to.be.true;
1111      });
1112
1113      mocha.it('10-6-2: should not call enableTimeAndMemoryPrint when perf is not ADVANCED', async function () {
1114        this.rollup.share.projectConfig.perf = PerfMode.NORMAL;
1115        const sourceProjectConfig = Object.assign(this.rollup.share.arkProjectConfig, this.rollup.share.projectConfig);
1116        await writeObfuscationCaches(sourceProjectConfig, undefined);
1117        await new Promise(resolve => setTimeout(resolve, 100));
1118        expect(fs.existsSync(timePerformanceFilePath)).to.be.false;
1119        expect(fs.existsSync(memoryPerformanceFilePath)).to.be.false;
1120      });
1121    });
1122
1123    mocha.describe('10-7: removeRedundantFiles', function () {
1124      let etsTestDir: string = 'test/ark_compiler_ut/testdata/testRemoveFiles/ets';
1125      let etsFortgzTestDir: string = 'test/ark_compiler_ut/testdata/testRemoveFiles/etsFortgz';
1126      let obfFilePath: string = 'test/ark_compiler_ut/testdata/testRemoveFiles/etsFortgz/a.d.ets';
1127      const sourceProjectConfig = {
1128        obfuscationOptions: {
1129          obfuscationCacheDir: 'test/ark_compiler_ut/testdata/testRemoveFiles/'
1130        }
1131      }
1132      const projectConfig = {
1133        projectRootPath: '',
1134        cachePath: '',
1135        aceModuleBuild: 'test/ark_compiler_ut/testdata/testRemoveFiles/ets',
1136        compileShared: true
1137      }
1138      mocha.before(function () {
1139        if (!fs.existsSync(etsTestDir)) {
1140          fs.mkdirSync(etsTestDir, { recursive: true });
1141        }
1142        if (!fs.existsSync(etsFortgzTestDir)) {
1143          fs.mkdirSync(etsFortgzTestDir, { recursive: true });
1144        }
1145        if (!fs.existsSync(obfFilePath)) {
1146          fs.writeFileSync(obfFilePath, 'test');
1147        }
1148      });
1149
1150      mocha.after(function () {
1151        if (fs.existsSync(obfFilePath)) {
1152          fs.unlinkSync(obfFilePath);
1153        }
1154        if (fs.existsSync(etsFortgzTestDir)) {
1155          fs.rmdirSync(etsFortgzTestDir, { recursive: true });
1156        }
1157        if (fs.existsSync(etsTestDir)) {
1158          fs.rmdirSync(etsTestDir, { recursive: true });
1159        }
1160      });
1161
1162      mocha.it('10-7-1: should not be remove when file is not obfuscated', async function () {
1163        let deletedFilesSet: Set<string> = new Set(['/test1.ets']);
1164        await removeRedundantFiles(sourceProjectConfig, deletedFilesSet, projectConfig);
1165        await new Promise(resolve => setTimeout(resolve, 100));
1166        expect(fs.existsSync(obfFilePath)).to.be.true;
1167      });
1168
1169      mocha.it('10-7-2: should be remove when file is obfuscated', async function () {
1170        let deletedFilesSet: Set<string> = new Set(['/test.ets']);
1171        await removeRedundantFiles(sourceProjectConfig, deletedFilesSet, projectConfig);
1172        await new Promise(resolve => setTimeout(resolve, 100));
1173        expect(fs.existsSync(obfFilePath)).to.be.false;
1174      });
1175    });
1176  });
1177});