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 { expect } from 'chai'; 18import { 19 ArkObfuscator, 20 clearGlobalCaches, 21 collectReservedNameForObf, 22 collectResevedFileNameInIDEConfig, 23 deleteLineInfoForNameString, 24 enableObfuscatedFilePathConfig, 25 enableObfuscateFileName, 26 generateConsumerObConfigFile, 27 getRelativeSourcePath, 28 handleObfuscatedFilePath, 29 handleUniversalPathInObf, 30 initObfuscationConfig, 31 mangleFilePath, 32 MemoryUtils, 33 MergedConfig, 34 nameCacheMap, 35 ObConfigResolver, 36 ObfuscationResultType, 37 orignalFilePathForSearching, 38 PropCollections, 39 readNameCache, 40 readProjectPropertiesByCollectedPaths, 41 renameFileNameModule, 42 ReseverdSetForArkguard, 43 TimeSumPrinter, 44 UnobfuscationCollections, 45 writeObfuscationNameCache, 46 writeUnobfuscationContent, 47 unobfuscationNamesObj, 48 FileUtils, 49} from '../../../src/ArkObfuscator'; 50 51import { 52 createSourceFile, 53 createObfTextSingleLineWriter, 54 RawSourceMap, 55 SourceFile, 56 ScriptTarget, 57} from 'typescript'; 58 59import { IOptions } from '../../../src/configs/IOptions'; 60import { getSourceMapGenerator } from '../../../src/utils/SourceMapUtil'; 61import { 62 globalFileNameMangledTable, 63 historyFileNameMangledTable, 64} from '../../../src/transformers/rename/RenameFileNameTransformer'; 65import { LocalVariableCollections } from '../../../src/utils/CommonCollections'; 66import { SOURCE_FILE_PATHS, projectWhiteListManager } from '../../../src/utils/ProjectCollections'; 67import { FilePathObj } from '../../../src/common/type'; 68import { historyAllUnobfuscatedNamesMap } from '../../../src/initialization/Initializer'; 69import path from 'path'; 70import { nameCache } from '../../../src/transformers/rename/RenameIdentifierTransformer'; 71import { 72 decodeSourcemap, 73 MappingsNameTypeForTest, 74 Source, 75 SourceMapLink 76} from '../../../src/utils/SourceMapMergingUtil'; 77 78describe('Tester Cases for <ArkObfuscator>', function () { 79 let obfuscator: ArkObfuscator; 80 let defaultConfig: IOptions; 81 82 const sourceFilePathObj: FilePathObj = { 83 buildFilePath: 'demo.ts', 84 relativeFilePath: 'demo', 85 }; 86 let sourceFile: SourceFile; 87 let sourceFileContent: string = `class Person { 88 constructor(public name: string, public age: number) { 89 this.name = name; 90 this.age = age; 91 } 92}`; 93 94 const jsSourceFilePathObj: FilePathObj = { 95 buildFilePath: 'demo.js', 96 relativeFilePath: '', 97 }; 98 let jsSourceFile: SourceFile; 99 let jsSourceFileContent: string = `//This is a comment 100//This is a comment 101function subtract(a, b) { 102 return a - b; 103}`; 104 105 const declSourceFilePathObj: FilePathObj = { 106 buildFilePath: 'demo.d.ts', 107 relativeFilePath: '', 108 }; 109 let declSourceFile: SourceFile; 110 let declSourceFileContent: string = `//This is a comment 111//This is a comment 112export declare function add(num1: number, num2: number): number; 113export declare function findElement<T>(arr: T[], callback: (item: T) => boolean): T | undefined;`; 114 115 beforeEach(() => { 116 obfuscator = new ArkObfuscator(); 117 118 // Clear the collection to ensure test isolation 119 PropCollections.clearPropsCollections(); 120 UnobfuscationCollections.clear(); 121 LocalVariableCollections.clear(); 122 123 defaultConfig = { 124 mRemoveComments: true, 125 mNameObfuscation: { 126 mEnable: true, 127 mNameGeneratorType: 1, 128 mReservedNames: [], 129 mRenameProperties: true, 130 mReservedProperties: [], 131 mTopLevel: true, 132 mReservedToplevelNames: [], 133 }, 134 mEnableSourceMap: true, 135 mEnableNameCache: true, 136 }; 137 138 sourceFile = createSourceFile(sourceFilePathObj.buildFilePath, sourceFileContent, ScriptTarget.ES2015, true); 139 jsSourceFile = createSourceFile(jsSourceFilePathObj.buildFilePath, jsSourceFileContent, ScriptTarget.ES2015, true); 140 declSourceFile = createSourceFile(declSourceFilePathObj.buildFilePath, declSourceFileContent, ScriptTarget.ES2015, true); 141 }); 142 143 describe('test for ArkObfuscator.init', () => { 144 it('should return false if config is undefined', () => { 145 const result = obfuscator.init(undefined); 146 expect(result).to.be.false; 147 }); 148 149 it('should return true if config is valid', () => { 150 const result = obfuscator.init(defaultConfig); 151 expect(result).to.be.true; 152 }); 153 154 it('source code should be compacted into one line', () => { 155 const config: IOptions = { 156 mCompact: true, 157 mEnableSourceMap: true, 158 mRemoveComments: true 159 }; 160 obfuscator.init(config); 161 162 let sourceMapGenerator = getSourceMapGenerator(jsSourceFilePathObj.buildFilePath); 163 const textWriter = createObfTextSingleLineWriter(); 164 obfuscator.createObfsPrinter(jsSourceFile.isDeclarationFile).writeFile(jsSourceFile, textWriter, sourceMapGenerator); 165 const actualContent = textWriter.getText(); 166 const expectContent = `function subtract(a, b) {return a - b;}`; 167 expect(actualContent === expectContent).to.be.true; 168 }); 169 170 it('should not init incremental cache when cachePath is not passed', () => { 171 const config: IOptions = { 172 mNameObfuscation: { 173 mEnable: true, 174 mRenameProperties: true, 175 mReservedProperties: [], 176 }, 177 mCompact: true, 178 mEnableSourceMap: true, 179 mRemoveComments: true 180 }; 181 obfuscator.init(config); 182 expect(obfuscator.fileContentManager).to.be.undefined; 183 expect(obfuscator.filePathManager).to.be.undefined; 184 expect(projectWhiteListManager).to.be.undefined; 185 }); 186 187 it('should init incremental cache when cachePath is passed', () => { 188 const config: IOptions = { 189 mNameObfuscation: { 190 mEnable: true, 191 mRenameProperties: true, 192 mReservedProperties: [], 193 }, 194 mCompact: true, 195 mEnableSourceMap: true, 196 mRemoveComments: true 197 }; 198 const cachePath = 'test/ut/utils/obfuscation'; 199 obfuscator.init(config, cachePath); 200 expect(obfuscator.fileContentManager).to.not.be.undefined; 201 expect(obfuscator.filePathManager).to.not.be.undefined; 202 expect(projectWhiteListManager).to.not.be.undefined; 203 }); 204 205 it('should set is incremental flag if is incremental', () => { 206 const config: IOptions = { 207 mNameObfuscation: { 208 mEnable: true, 209 mRenameProperties: true, 210 mReservedProperties: [], 211 }, 212 mCompact: true, 213 mEnableSourceMap: true, 214 mRemoveComments: true 215 }; 216 const cachePath = 'test/ut/utils/obfuscation'; 217 const filePathsCache = path.join(cachePath, SOURCE_FILE_PATHS); 218 let content = 'hello'; 219 FileUtils.writeFile(filePathsCache, content); 220 obfuscator.init(config, cachePath); 221 expect(obfuscator.isIncremental).to.be.true; 222 FileUtils.deleteFile(filePathsCache); 223 }); 224 }); 225 226 describe('test for ArkObfuscator.obfuscate', () => { 227 it('should return empty result for ignored files', async () => { 228 const sourceFilePathObj: FilePathObj = { 229 buildFilePath: 'ignoredFile.cpp', 230 relativeFilePath: '', 231 }; 232 const result: ObfuscationResultType = await obfuscator.obfuscate( 233 'hello world', 234 sourceFilePathObj, 235 ); 236 expect(result).to.deep.equal({ content: undefined }); 237 }); 238 239 it('should return empty result for empty AST', async () => { 240 const sourceFilePathObj: FilePathObj = { 241 buildFilePath: 'emptyFile.js', 242 relativeFilePath: '', 243 }; 244 const result: ObfuscationResultType = await obfuscator.obfuscate('', sourceFilePathObj); 245 expect(result).to.deep.equal({ content: undefined }); 246 }); 247 248 it('should be correctly obfuscated for valid AST', async () => { 249 obfuscator.init(defaultConfig); 250 const result: ObfuscationResultType = await obfuscator.obfuscate( 251 sourceFile, 252 sourceFilePathObj, 253 ); 254 const expectResult = `class g { 255 constructor(public name: string, public h: number) { 256 this.name = name; 257 this.h = h; 258 } 259} 260`; 261 expect(result.content === expectResult).to.be.true; 262 }); 263 264 it('comments in declaration file should be removed when enable -remove-comments', async () => { 265 const config: IOptions = { 266 mRemoveDeclarationComments: { 267 mEnable: true, 268 mReservedComments: [], 269 mUniversalReservedComments: [], 270 }, 271 }; 272 273 obfuscator.init(config); 274 const result: ObfuscationResultType = await obfuscator.obfuscate(declSourceFile, declSourceFilePathObj); 275 const expectResult = `export declare function add(num1: number, num2: number): number; 276export declare function findElement<T>(arr: T[], callback: (item: T) => boolean): T | undefined; 277`; 278 expect(result.content === expectResult).to.be.true; 279 }); 280 281 it('comments in declaration file should not be removed when enable -remove-comments', async () => { 282 const config: IOptions = { 283 mRemoveDeclarationComments: { 284 mEnable: false, 285 mReservedComments: [], 286 mUniversalReservedComments: [], 287 }, 288 }; 289 obfuscator.init(config); 290 const result: ObfuscationResultType = await obfuscator.obfuscate(declSourceFile, declSourceFilePathObj); 291 const expectResult = `//This is a comment 292//This is a comment 293export declare function add(num1: number, num2: number): number; 294export declare function findElement<T>(arr: T[], callback: (item: T) => boolean): T | undefined; 295`; 296 expect(result.content === expectResult).to.be.true; 297 }); 298 299 it('unobfuscationNameMap should be Map type when enable -print-kept-names', async () => { 300 const config = { 301 mUnobfuscationOption: { 302 mPrintKeptNames: true, 303 mPrintPath: 'local.json', 304 }, 305 }; 306 historyAllUnobfuscatedNamesMap.set('demo', {'key': ['value']}); 307 obfuscator.init(config); 308 const result: ObfuscationResultType = await obfuscator.obfuscate( 309 sourceFile, 310 sourceFilePathObj, 311 ); 312 expect(result.unobfuscationNameMap instanceof Map).to.be.true; 313 }); 314 315 it('unobfuscationNameMap should be undefined when disable -print-kept-names, ', async () => { 316 obfuscator.init(defaultConfig); 317 const result: ObfuscationResultType = await obfuscator.obfuscate( 318 sourceFile, 319 sourceFilePathObj, 320 ); 321 expect(result.unobfuscationNameMap === undefined).to.be.true; 322 }); 323 324 it('historyNameCache should be used when provide historyNameCache', async () => { 325 obfuscator.init(defaultConfig); 326 const historyNameCache = new Map([['#Person', 'm'], ['Person:2:5', 'm']]); 327 const result: ObfuscationResultType = await obfuscator.obfuscate( 328 sourceFile, 329 sourceFilePathObj, 330 undefined, 331 historyNameCache, 332 ); 333 const expectResult = ` 334 class m { 335 constructor(public name: string, public g: number) { 336 this.name = name; 337 this.g = g; 338 } 339 } 340 `; 341 expect(compareStringsIgnoreNewlines(result.content, expectResult)).to.be.true; 342 }); 343 344 it('fileName should be obfuscated when enable -enable-filename-obfuscation', async () => { 345 const config: IOptions = { 346 mRenameFileName: { 347 mEnable: true, 348 mNameGeneratorType: 1, 349 mReservedFileNames: [], 350 }, 351 }; 352 obfuscator.init(config); 353 const result: ObfuscationResultType = await obfuscator.obfuscate( 354 sourceFile, 355 sourceFilePathObj, 356 ); 357 358 expect(orignalFilePathForSearching === 'demo.ts').to.be.true; 359 expect(result.filePath === 'a.ts').to.be.true; 360 }); 361 362 it('PropCollections shoule be cleared when only enable toplevel option', async () => { 363 PropCollections.globalMangledTable.set('test', 'obfuscated'); 364 const config: IOptions = { 365 mNameObfuscation: { 366 mEnable: true, 367 mNameGeneratorType: 1, 368 mRenameProperties: false, 369 mReservedProperties: [], 370 mTopLevel: true, 371 }, 372 mExportObfuscation: false, 373 }; 374 obfuscator.init(config); 375 await obfuscator.obfuscate(sourceFile, sourceFilePathObj); 376 expect(PropCollections.globalMangledTable.size).to.equal(0); 377 }); 378 379 it('PropCollections shoule not be cleared when enable toplevel、property and export option', async () => { 380 PropCollections.globalMangledTable.set('test', 'obfuscated'); 381 const config: IOptions = { 382 mNameObfuscation: { 383 mEnable: true, 384 mNameGeneratorType: 1, 385 mRenameProperties: true, 386 mReservedProperties: [], 387 mTopLevel: true, 388 }, 389 mExportObfuscation: true, 390 }; 391 obfuscator.init(config); 392 await obfuscator.obfuscate(sourceFile, sourceFilePathObj); 393 expect(PropCollections.globalMangledTable.get('test') === 'obfuscated').to.be.true; 394 }); 395 396 it('test for use sourcemap mapping', async () => { 397 obfuscator.init(defaultConfig); 398 const previousStageSourceMap = { 399 "version":3, 400 "file":"demo.js", 401 "sourceRoot":"", 402 "sources":["demo.js"], 403 "names":[], 404 "mappings":"AAAA,mBAAmB;AACnB,mBAAmB;AACnB,SAAS,QAAQ,CAAC,CAAC,EAAE,CAAC;IAClB,OAAO,CAAC,GAAG,CAAC,CAAC;AACjB,CAAC" 405 } as RawSourceMap; 406 const result: ObfuscationResultType = await obfuscator.obfuscate( 407 jsSourceFile, 408 jsSourceFilePathObj, 409 previousStageSourceMap, 410 ); 411 const actualSourceMap = JSON.stringify(result.sourceMap); 412 const expectSourceMap = `{"version":3,"file":"demo.js","sources":["demo.js"],"names":[], 413 "mappings":"AAEA,WAAkB,CAAC,EAAE,CAAC;IAClB,OAAO,KAAK,CAAC;AACjB,CAAC","sourceRoot":""}`; 414 expect(compareStringsIgnoreNewlines(actualSourceMap, expectSourceMap)).to.be.true; 415 }); 416 417 it('test for not use sourcemap mapping', async () => { 418 obfuscator.init(defaultConfig); 419 const result: ObfuscationResultType = await obfuscator.obfuscate( 420 jsSourceFile, 421 jsSourceFilePathObj, 422 ); 423 const actualSourceMap = JSON.stringify(result.sourceMap); 424 const expectSourceMap = `{"version":3,"file":"demo.js","sourceRoot":"","sources":["demo.js"], 425 "names":[],"mappings":"AAEA,WAAkB,CAAC,EAAE,CAAC;IAClB,OAAO,KAAK,CAAC;AACjB,CAAC"}`; 426 expect(compareStringsIgnoreNewlines(actualSourceMap, expectSourceMap)).to.be.true; 427 }); 428 }); 429 430 describe('test for ArkObfuscator.setWriteOriginalFile', () => { 431 it('should set writeOriginalFile to true', () => { 432 obfuscator.setWriteOriginalFile(true); 433 expect(obfuscator.getWriteOriginalFileForTest()).to.be.true; 434 }); 435 436 it('should set writeOriginalFile to false', () => { 437 obfuscator.setWriteOriginalFile(false); 438 expect(obfuscator.getWriteOriginalFileForTest()).to.be.false; 439 }); 440 }); 441 442 describe('test for ArkObfuscator.addReservedSetForPropertyObf', () => { 443 it('should add reserved sets correctly', () => { 444 const properties: ReseverdSetForArkguard = { 445 structPropertySet: new Set(['struct1']), 446 stringPropertySet: new Set(['string1']), 447 exportNameAndPropSet: new Set(['export1']), 448 exportNameSet: undefined, 449 enumPropertySet: new Set(['enum1']), 450 }; 451 452 obfuscator.addReservedSetForPropertyObf(properties); 453 454 expect(UnobfuscationCollections.reservedStruct.has('struct1')).to.be.true; 455 expect(UnobfuscationCollections.reservedStrProp.has('string1')).to.be.true; 456 expect(UnobfuscationCollections.reservedExportNameAndProp.has('export1')).to.be.true; 457 expect(UnobfuscationCollections.reservedEnum.has('enum1')).to.be.true; 458 }); 459 460 it('should not add empty sets', () => { 461 const properties: ReseverdSetForArkguard = { 462 structPropertySet: new Set(), 463 stringPropertySet: new Set(), 464 exportNameAndPropSet: new Set(), 465 exportNameSet: undefined, 466 enumPropertySet: new Set(), 467 }; 468 469 obfuscator.addReservedSetForPropertyObf(properties); 470 471 expect(UnobfuscationCollections.reservedStruct.size).to.equal(0); 472 expect(UnobfuscationCollections.reservedStrProp.size).to.equal(0); 473 expect(UnobfuscationCollections.reservedExportNameAndProp.size).to.equal(0); 474 expect(UnobfuscationCollections.reservedEnum.size).to.equal(0); 475 }); 476 }); 477 478 describe('test for ArkObfuscator.addReservedSetForDefaultObf', () => { 479 it('should add reserved export name set correctly', () => { 480 const properties: ReseverdSetForArkguard = { 481 structPropertySet: undefined, 482 stringPropertySet: undefined, 483 exportNameAndPropSet: undefined, 484 exportNameSet: new Set(['exportName1']), 485 enumPropertySet: undefined, 486 }; 487 488 obfuscator.addReservedSetForDefaultObf(properties); 489 expect(UnobfuscationCollections.reservedExportName.has('exportName1')).to.be.true; 490 }); 491 }); 492 493 describe('test for ArkObfuscator.setKeepSourceOfPaths', () => { 494 it('should set the keep source of paths correctly', () => { 495 const config: IOptions = { 496 mKeepFileSourceCode: { 497 mKeepSourceOfPaths: new Set(), 498 mkeepFilesAndDependencies: new Set(), 499 }, 500 }; 501 obfuscator.init(config); 502 503 const paths = new Set(['path1', 'path2']); 504 obfuscator.setKeepSourceOfPaths(paths); 505 expect(obfuscator.customProfiles.mKeepFileSourceCode?.mKeepSourceOfPaths).to.equal(paths); 506 }); 507 }); 508 509 describe('test for ArkObfuscator.isCurrentFileInKeepPaths', () => { 510 it('should return false if mKeepSourceOfPaths is empty', () => { 511 const customProfiles: IOptions = { 512 mKeepFileSourceCode: { 513 mKeepSourceOfPaths: new Set(), 514 mkeepFilesAndDependencies: new Set(), 515 }, 516 }; 517 const result = obfuscator.isCurrentFileInKeepPathsForTest(customProfiles, 'some/file/path.js'); 518 expect(result).to.be.false; 519 }); 520 521 it('should return true if originalFilePath is in mKeepSourceOfPaths', () => { 522 const keepPaths = new Set(['some/file/path.js']); 523 const customProfiles: IOptions = { 524 mKeepFileSourceCode: { 525 mKeepSourceOfPaths: keepPaths, 526 mkeepFilesAndDependencies: new Set(), 527 } 528 }; 529 const result = obfuscator.isCurrentFileInKeepPathsForTest(customProfiles, 'some/file/path.js'); 530 expect(result).to.be.true; 531 }); 532 }); 533 534 describe('test for ArkObfuscator.convertLineBasedOnSourceMap', () => { 535 it('there is no location but the value is obfuscated, it should be recorded in nameacahe', () => { 536 const identifierCache = new Map<string, string>([ 537 ['#Person', 'Person'], 538 ['obfsucationValue:31:5:35:6', 'h'], 539 ['getName:75:5:77:6', 'getName'] 540 ]); 541 nameCache.set('IdentifierCache', identifierCache); 542 const source: Source = new Source('utils.ets', null); 543 const previousStageSourceMap: RawSourceMap = { 544 version: 3, 545 file: 'utils.ets', 546 sourceRoot: '', 547 sources: [ 'entry/src/main/ets/pages/utils/utils.ets'], 548 names: [], 549 mappings: '', 550 sourcesContent: undefined, 551 } 552 const decodedSourceMap = decodeSourcemap(previousStageSourceMap as RawSourceMap); 553 const sourceMapLink: SourceMapLink = new SourceMapLink(decodedSourceMap as MappingsNameTypeForTest, [source]); 554 555 const result = obfuscator.convertLineBasedOnSourceMapForTest('IdentifierCache', sourceMapLink); 556 const expectedResult= { 557 '#Person': 'Person', 558 'obfsucationValue': 'h' 559 }; 560 const compareResult = JSON.stringify(result) === JSON.stringify(expectedResult); 561 expect(compareResult).to.be.true; 562 }); 563 564 it('there is start and end location, it should be recorded in nameacahe', () => { 565 const identifierCache = new Map<string, string>([ 566 ['#Person', 'Person'], 567 ['#foo:1:1:3:2', 'foo'], 568 ['getName:75:5:77:6', 'getName'] 569 ]); 570 nameCache.set('IdentifierCache', identifierCache); 571 const source: Source = new Source('file.ts', null); 572 const previousStageSourceMap: RawSourceMap = { 573 "version": 3, 574 "file": "file.ts", 575 "sources": [ 576 "entry/src/main/ets/pages/file.ts" 577 ], 578 "names": [], 579 "mappings": "AAAA,MAAM,UAAU,GAAG;IACjB,OAAO,CAAC,CAAC;AACX,CAAC", 580 "sourceRoot": "" 581 } 582 const decodedSourceMap = decodeSourcemap(previousStageSourceMap as RawSourceMap); 583 const sourceMapLink: SourceMapLink = new SourceMapLink(decodedSourceMap as MappingsNameTypeForTest, [source]); 584 585 const result = obfuscator.convertLineBasedOnSourceMapForTest('IdentifierCache', sourceMapLink); 586 const expectedResult= { 587 '#Person': 'Person', 588 '#foo:1:3': 'foo' 589 }; 590 const compareResult = JSON.stringify(result) === JSON.stringify(expectedResult); 591 expect(compareResult).to.be.true; 592 }); 593 }); 594 595 describe('test for clearGlobalCaches', () => { 596 beforeEach(() => { 597 PropCollections.globalMangledTable.set('test1', 'obfuscated1'); 598 PropCollections.historyMangledTable = new Map([['test2', 'obfuscated2']]); 599 PropCollections.reservedProperties.add('reserved1'); 600 PropCollections.universalReservedProperties.push(/universal\d+/); 601 globalFileNameMangledTable.set('key1', 'value1'); 602 renameFileNameModule.historyFileNameMangledTable = new Map([['keyA', 'valueA']]); 603 UnobfuscationCollections.reservedSdkApiForProp.add('api1'); 604 UnobfuscationCollections.reservedSdkApiForGlobal.add('globalApi1'); 605 UnobfuscationCollections.reservedSdkApiForLocal.add('localApi1'); 606 UnobfuscationCollections.reservedStruct.add('struct1'); 607 UnobfuscationCollections.reservedLangForProperty.add('lang1'); 608 UnobfuscationCollections.reservedExportName.add('exportName1'); 609 UnobfuscationCollections.reservedExportNameAndProp.add('exportNameAndProp1'); 610 UnobfuscationCollections.reservedStrProp.add('stringProp1'); 611 UnobfuscationCollections.reservedEnum.add('enum1'); 612 UnobfuscationCollections.unobfuscatedPropMap.set('age', new Set(['key', 'value'])); 613 UnobfuscationCollections.unobfuscatedNamesMap.set('name1', new Set(['key1', 'value2'])); 614 LocalVariableCollections.reservedConfig.add('localConfig1'); 615 }); 616 617 it('should clear all global caches', () => { 618 clearGlobalCaches(); 619 620 expect(PropCollections.globalMangledTable.size).to.equal(0); 621 expect(PropCollections.historyMangledTable.size).to.equal(0); 622 expect(PropCollections.reservedProperties.size).to.equal(0); 623 expect(PropCollections.universalReservedProperties.length).to.equal(0); 624 expect(globalFileNameMangledTable.size).to.equal(0); 625 expect(historyFileNameMangledTable.size).to.equal(0); 626 expect(UnobfuscationCollections.reservedSdkApiForProp.size).to.equal(0); 627 expect(UnobfuscationCollections.reservedStruct.size).to.equal(0); 628 expect(UnobfuscationCollections.reservedExportName.size).to.equal(0); 629 expect(LocalVariableCollections.reservedConfig.size).to.equal(0); 630 }); 631 }); 632 633 describe('test whether the methods exported from the ArkObfuscator file exist', () => { 634 it('The ArkObfuscator export the collectReservedNameForObf method', () => { 635 expect(collectReservedNameForObf).to.exist; 636 }); 637 638 it('The ArkObfuscator export the collectResevedFileNameInIDEConfig method', () => { 639 expect(collectResevedFileNameInIDEConfig).to.exist; 640 }); 641 642 it('The ArkObfuscator export the deleteLineInfoForNameString method', () => { 643 expect(deleteLineInfoForNameString).to.exist; 644 }); 645 646 it('The ArkObfuscator export the enableObfuscatedFilePathConfig method', () => { 647 expect(enableObfuscatedFilePathConfig).to.exist; 648 }); 649 650 it('The ArkObfuscator export the enableObfuscateFileName method', () => { 651 expect(enableObfuscateFileName).to.exist; 652 }); 653 654 it('The ArkObfuscator export the generateConsumerObConfigFile method', () => { 655 expect(generateConsumerObConfigFile).to.exist; 656 }); 657 658 it('The ArkObfuscator export the getRelativeSourcePath method', () => { 659 expect(getRelativeSourcePath).to.exist; 660 }); 661 662 it('The ArkObfuscator export the handleObfuscatedFilePath method', () => { 663 expect(handleObfuscatedFilePath).to.exist; 664 }); 665 666 it('The ArkObfuscator export the handleUniversalPathInObf method', () => { 667 expect(handleUniversalPathInObf).to.exist; 668 }); 669 670 it('The ArkObfuscator export the initObfuscationConfig method', () => { 671 expect(initObfuscationConfig).to.exist; 672 }); 673 674 it('The ArkObfuscator export the mangleFilePath method', () => { 675 expect(mangleFilePath).to.exist; 676 }); 677 678 it('The ArkObfuscator export the MemoryUtils method', () => { 679 expect(MemoryUtils).to.exist; 680 }); 681 682 it('The ArkObfuscator export the MergedConfig method', () => { 683 expect(MergedConfig).to.exist; 684 }); 685 686 it('The ArkObfuscator export the nameCacheMap method', () => { 687 expect(nameCacheMap).to.exist; 688 }); 689 690 it('The ArkObfuscator export the ObConfigResolver method', () => { 691 expect(ObConfigResolver).to.exist; 692 }); 693 694 it('The ArkObfuscator export the readNameCache method', () => { 695 expect(readNameCache).to.exist; 696 }); 697 698 it('The ArkObfuscator export the readProjectPropertiesByCollectedPaths method', () => { 699 expect(readProjectPropertiesByCollectedPaths).to.exist; 700 }); 701 702 it('The ArkObfuscator export the TimeSumPrinter method', () => { 703 expect(TimeSumPrinter).to.exist; 704 }); 705 706 it('The ArkObfuscator export the writeObfuscationNameCache method', () => { 707 expect(writeObfuscationNameCache).to.exist; 708 }); 709 710 it('The ArkObfuscator export the writeUnobfuscationContent method', () => { 711 expect(writeUnobfuscationContent).to.exist; 712 }); 713 714 it('The ArkObfuscator export the unobfuscationNamesObj method', () => { 715 expect(unobfuscationNamesObj).to.exist; 716 }); 717 }); 718}); 719 720function compareStringsIgnoreNewlines(str1: string, str2: string): boolean { 721 const normalize = (str: string) => str.replace(/[\n\r\s]+/g, ''); 722 return normalize(str1) === normalize(str2); 723} 724