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 { assert, expect } from 'chai'; 18import { 19 ObOptionsForTest, 20 ObConfigResolver, 21 MergedConfig, 22 collectResevedFileNameInIDEConfig, 23 readNameCache, 24 handleUniversalPathInObf, 25 getArkguardNameCache, 26 fillNameCache, 27 writeObfuscationNameCache, 28 generateConsumerObConfigFile, 29 mangleFilePath, 30 enableObfuscatedFilePathConfig, 31 handleObfuscatedFilePath, 32 enableObfuscateFileName, 33 getRelativeSourcePath, 34 OptionTypeForTest, 35 SourceObConfig, 36 Obfuscation, 37 printUnobfuscationReasons, 38 clearNameCache 39} from '../../../src/initialization/ConfigResolver'; 40import { HvigorErrorInfo, PropCollections, renameFileNameModule } from '../../../src/ArkObfuscator'; 41import { 42 clearUnobfuscationNamesObj, 43 nameCacheMap, 44 unobfuscationNamesObj 45} from '../../../src/initialization/CommonObject'; 46import path from 'path'; 47import fs from 'fs'; 48import { FileUtils } from '../../../src/utils/FileUtils'; 49import sinon from 'sinon'; 50import { AtKeepCollections, UnobfuscationCollections } from '../../../src/utils/CommonCollections'; 51import { 52 clearHistoryUnobfuscatedMap, 53 historyAllUnobfuscatedNamesMap, 54 historyUnobfuscatedPropMap 55} from '../../../src/initialization/Initializer'; 56 57const OBFUSCATE_TESTDATA_DIR = path.resolve(__dirname, '../../testData/obfuscation/system_api_obfuscation'); 58const projectConfig = { 59 obfuscationOptions: { option1: 'value1' }, 60 compileHar: true 61}; 62 63function printObfLogger(errorInfo: string, errorCodeInfo: HvigorErrorInfo | string, level: string): void { 64 switch (level) { 65 case 'warn': 66 console.warn(errorInfo); 67 break; 68 case 'error': 69 console.error(errorInfo); 70 break; 71 default: 72 break; 73 } 74} 75 76function printObfHvigorLogger(errorInfo: string, errorCodeInfo: HvigorErrorInfo | string, level: string): void { 77 switch (level) { 78 case 'warn': 79 console.warn(errorCodeInfo); 80 break; 81 case 'error': 82 console.error(errorCodeInfo); 83 break; 84 default: 85 break; 86 } 87} 88 89const logger = console; 90const isTerser = false; 91let newObConfigResolver = new ObConfigResolver(projectConfig, printObfLogger, isTerser); 92 93describe('test for ConfigResolve', function() { 94 describe('ObOptions', () => { 95 it('should merge options correctly', () => { 96 const ob1 = new ObOptionsForTest(); 97 ob1.disableObfuscation = true; 98 ob1.enablePropertyObfuscation = true; 99 100 const ob2 = new ObOptionsForTest(); 101 ob2.enableToplevelObfuscation = true; 102 ob2.printNameCache = 'test'; 103 ob2.printKeptNamesPath = './test/ut/initialization/printKeptNamesPath.txt'; 104 ob2.applyNameCache = 'test case'; 105 106 ob1.mergeObOptions(ob2); 107 108 expect(ob1.disableObfuscation).to.be.true; 109 expect(ob1.enablePropertyObfuscation).to.be.true; 110 expect(ob1.enableToplevelObfuscation).to.be.true; 111 expect(ob1.printNameCache).to.equal('test'); 112 expect(ob1.printKeptNamesPath).to.equal('./test/ut/initialization/printKeptNamesPath.txt'); 113 expect(ob1.applyNameCache).to.equal('test case'); 114 }); 115 }); 116 117 describe('MergedConfig', () => { 118 describe('should merge two MergedConfig instances correctly', () => { 119 it('merge arrays and sets in MergeConfig', () => { 120 const config1 = new MergedConfig(); 121 config1.reservedPropertyNames = ['prop1']; 122 config1.reservedGlobalNames = ['global1']; 123 config1.keepComments = ['comment1']; 124 config1.excludePathSet.add('path1'); 125 126 const config2 = new MergedConfig(); 127 config2.reservedPropertyNames = ['prop2']; 128 config2.reservedGlobalNames = ['global2']; 129 config2.keepComments = ['comment2']; 130 config2.excludePathSet.add('path2'); 131 132 config1.mergeAllRules(config2); 133 134 expect(config1.reservedPropertyNames).to.deep.equal(['prop1', 'prop2']); 135 expect(config1.reservedGlobalNames).to.deep.equal(['global1', 'global2']); 136 expect(config1.keepComments).to.deep.equal(['comment1', 'comment2']); 137 expect(config1.excludePathSet).to.deep.equal(new Set(['path1', 'path2'])); 138 }); 139 140 it('merge options in MergeConfig', () => { 141 const config1 = new MergedConfig(); 142 config1.options.enableExportObfuscation = false; 143 config1.options.stripLanguageDefault = true; 144 config1.options.stripSystemApiArgs = true; 145 146 const config2 = new MergedConfig(); 147 config2.options.enableExportObfuscation = true; 148 config2.options.stripLanguageDefault = false; 149 config2.options.stripSystemApiArgs = true; 150 config1.mergeAllRules(config2); 151 152 expect(config1.options.disableObfuscation).to.be.false; 153 expect(config1.options.enablePropertyObfuscation).to.be.false; 154 expect(config1.options.enableToplevelObfuscation).to.be.false; 155 expect(config1.options.enableStringPropertyObfuscation).to.be.false; 156 expect(config1.options.removeLog).to.be.false; 157 expect(config1.options.compact).to.be.false; 158 expect(config1.options.removeComments).to.be.false; 159 expect(config1.options.enableFileNameObfuscation).to.be.false; 160 expect(config1.options.enableExportObfuscation).to.be.true; 161 expect(config1.options.stripLanguageDefault).to.be.true; 162 expect(config1.options.stripSystemApiArgs).to.be.true; 163 }); 164 }); 165 166 it('should sort and deduplicate arrays correctly', () => { 167 const config = new MergedConfig(); 168 config.reservedPropertyNames = ['prop2', 'prop1', 'prop1']; 169 config.reservedGlobalNames = ['global2', 'global1', 'global1']; 170 config.keepComments = ['comment2', 'comment1', 'comment1']; 171 172 config.sortAndDeduplicate(); 173 174 expect(config.reservedPropertyNames).to.deep.equal(['prop1', 'prop2']); 175 expect(config.reservedGlobalNames).to.deep.equal(['global1', 'global2']); 176 expect(config.keepComments).to.deep.equal(['comment1', 'comment2']); 177 }); 178 179 it('should serialize merged config correctly', () => { 180 let resultStr: string = ''; 181 const config = new MergedConfig(); 182 config.options = new ObOptionsForTest(); 183 config.options['option1'] = true; 184 config.options['option2'] = false; 185 config.options['disableObfuscation'] = true; 186 config.options['enableStringPropertyObfuscation'] = true; 187 config.reservedGlobalNames = ['global1']; 188 config.reservedPropertyNames = ['prop1']; 189 190 const serialized = config.serializeMergedConfig(); 191 const serializedExportSwitchMap = new Map([ 192 ['disableObfuscation', ObConfigResolver.KEEP_DTS], 193 ['enablePropertyObfuscation', ObConfigResolver.ENABLE_PROPERTY_OBFUSCATION], 194 ['enableStringPropertyObfuscation', ObConfigResolver.ENABLE_STRING_PROPERTY_OBFUSCATION], 195 ['enableToplevelObfuscation', ObConfigResolver.ENABLE_TOPLEVEL_OBFUSCATION], 196 ['compact', ObConfigResolver.COMPACT], 197 ['removeLog', ObConfigResolver.REMOVE_LOG], 198 ]); 199 200 expect(serialized).to.include(ObConfigResolver.KEEP_GLOBAL_NAME); 201 expect(serialized).to.include('global1'); 202 expect(serialized).to.include(ObConfigResolver.KEEP_PROPERTY_NAME); 203 expect(serialized).to.include('prop1'); 204 expect(serialized).to.not.include('option2'); 205 206 expect(ObConfigResolver.exportedSwitchMap.has(String('disableObfuscation'))).to.be.false; 207 expect(ObConfigResolver.exportedSwitchMap.has(String('enableStringPropertyObfuscation'))).to.be.true; 208 expect(resultStr).to.equal(''); 209 }); 210 }); 211 212 describe('ObConfigResolver', () => { 213 describe('constructor', () => { 214 it('should create an instance with the correct properties', () => { 215 const projectConfig = { 216 obfuscationOptions: { option1: 'value1' }, 217 compileHar: true 218 }; 219 const isTerser = false; 220 const myInstance = new ObConfigResolver(projectConfig, printObfLogger, isTerser); 221 222 expect(myInstance).to.be.an('object'); 223 expect(myInstance.sourceObConfig).to.deep.equal({ option1: 'value1' }); 224 expect(myInstance.isHarCompiled).to.be.true; 225 expect(myInstance.isTerser).to.be.false; 226 }); 227 228 it('should create an instance with Terser enabled', () => { 229 const projectConfig = { 230 obfuscationOptions: { option1: 'value1' }, 231 compileHar: true 232 }; 233 const myInstance = new ObConfigResolver(projectConfig, printObfLogger, true); 234 235 expect(myInstance).to.be.an('object'); 236 expect(myInstance.sourceObConfig).to.deep.equal({ option1: 'value1' }); 237 expect(myInstance.isHarCompiled).to.be.true; 238 expect(myInstance.isTerser).to.be.true; 239 }); 240 }); 241 242 describe('resolveObfuscationConfigs', () => { 243 const projectConfig = { 244 obfuscationOptions: { option1: 'value1' }, 245 compileHar: true 246 }; 247 const logger = console; 248 const isTerser = false; 249 let newObConfigResolver = new ObConfigResolver(projectConfig, printObfLogger, isTerser); 250 let testClass: ObConfigResolver & { 251 performancePrinter?: any; 252 }; 253 testClass = newObConfigResolver; 254 255 it('should return a MergedConfig object when sourceObConfig is undefined', () => { 256 testClass.sourceObConfig = undefined; 257 testClass.isHarCompiled = true; 258 testClass.performancePrinter = {}; 259 const result = testClass.resolveObfuscationConfigs(); 260 generateConsumerObConfigFile(testClass.sourceObConfig, undefined); 261 262 expect(testClass.sourceObConfig).to.be.an.undefined; 263 expect(result).to.deep.equal(new MergedConfig()); 264 expect(result).to.be.an('object'); 265 expect(result).to.have.property('options'); 266 }); 267 268 it('should return a MergedConfig object when sourceObConfig is null', () => { 269 testClass.sourceObConfig = null; 270 testClass.isHarCompiled = true; 271 testClass.performancePrinter = {}; 272 const result = testClass.resolveObfuscationConfigs(); 273 generateConsumerObConfigFile(null, undefined); 274 275 expect(testClass.sourceObConfig).to.be.a.null; 276 expect(result).to.deep.equal(new MergedConfig()); 277 expect(result).to.be.an('object'); 278 expect(result).to.have.property('options'); 279 }); 280 281 it('should handle the case when sourceObConfig.selfConfig.ruleOptions.enable is false', function () { 282 testClass.sourceObConfig = { 283 selfConfig: { 284 ruleOptions: { enable: false }, 285 }, 286 dependencies: { libraries: [], hars: [] }, 287 }; 288 generateConsumerObConfigFile(testClass.sourceObConfig, undefined); 289 const result = testClass.resolveObfuscationConfigs(); 290 291 expect(result).to.be.an('object'); 292 expect(result).to.have.property('options'); 293 expect(result.options.disableObfuscation).to.be.true; 294 }); 295 296 it('should handle the case when sourceObConfig.selfConfig.ruleOptions.enable is true', function () { 297 testClass.sourceObConfig = { 298 selfConfig: { 299 ruleOptions: { enable: true }, 300 }, 301 dependencies: { libraries: [], hars: [] }, 302 }; 303 generateConsumerObConfigFile(testClass.sourceObConfig, undefined); 304 const result = testClass.resolveObfuscationConfigs(); 305 306 expect(result).to.be.an('object'); 307 expect(result).to.have.property('options'); 308 expect(result.options.disableObfuscation).to.be.false; 309 }); 310 311 it('should handle the case when enableObfuscation is false', () => { 312 const sourceObConfig = { 313 selfConfig: { 314 ruleOptions: { enable: false }, 315 consumerRules: ['./test/testData/obfuscation/keepDts/obfuscation-template.txt'], 316 }, 317 dependencies: { libraries: [], hars: [] }, 318 obfuscationCacheDir: './test/testData/cache', 319 options: { 320 disableObfuscation: true 321 }, 322 exportRulePath: '', 323 sdkApis: [] 324 }; 325 const isHarCompiled = true; 326 let enableObfuscation = sourceObConfig.selfConfig.ruleOptions.enable; 327 let selfConfig = new MergedConfig(); 328 enableObfuscation = !selfConfig.options.disableObfuscation; 329 let needConsumerConfigs = isHarCompiled && sourceObConfig.selfConfig.consumerRules && 330 sourceObConfig.selfConfig.consumerRules.length > 0; 331 let needDependencyConfigs = enableObfuscation || needConsumerConfigs; 332 let dependencyConfigs = new MergedConfig(); 333 const dependencyMaxLength = Math.max( 334 sourceObConfig.dependencies.libraries.length, 335 sourceObConfig.dependencies.hars.length, 336 ); 337 newObConfigResolver.getDependencyConfigsForTest(sourceObConfig, dependencyConfigs); 338 339 expect(needConsumerConfigs).to.be.true; 340 expect(!dependencyMaxLength).to.be.true; 341 expect(needDependencyConfigs).to.be.true; 342 expect(dependencyConfigs).to.deep.equal(new MergedConfig()); 343 expect(enableObfuscation).to.be.true; 344 }); 345 346 it('should handle the case when enableObfuscation is false', () => { 347 const localHarConfig = { 348 selfConfig: { 349 ruleOptions: { 350 enable: true, 351 rules: ['./test/testData/obfuscation/Configs/localHar/obfuscation-rules.txt'] 352 }, 353 consumerRules: [], 354 libDir: "", 355 consumerFiles: "" 356 }, 357 dependencies: { libraries: [], hars: [] }, 358 sdkApis: [], 359 obfuscationCacheDir: '', 360 exportRulePath: '' 361 }; 362 363 const sourceObConfig = { 364 selfConfig: { 365 options: { 366 disableObfuscation: false, 367 enablePropertyObfuscation: true, 368 enableExportObfuscation: true, 369 enableToplevelObfuscation: true 370 }, 371 ruleOptions: { enable: true }, 372 consumerRules: ['./test/testData/obfuscation/keepDts/obfuscation-template.txt'], 373 libDir: '' 374 }, 375 dependencies: { libraries: [localHarConfig.selfConfig], hars: [] }, 376 obfuscationCacheDir: './test/testData/cache', 377 sdkApis: [], 378 exportRulePath: '' 379 }; 380 const isHarCompiled = true; 381 let enableObfuscation = sourceObConfig.selfConfig.ruleOptions.enable; 382 let selfConfig = new MergedConfig(); 383 enableObfuscation = !selfConfig.options.disableObfuscation; 384 let needConsumerConfigs = isHarCompiled && sourceObConfig.selfConfig.consumerRules && 385 sourceObConfig.selfConfig.consumerRules.length > 0; 386 let needDependencyConfigs = enableObfuscation || needConsumerConfigs; 387 let dependencyConfigs = new MergedConfig(); 388 const dependencyMaxLength = Math.max( 389 sourceObConfig.dependencies.libraries.length, 390 sourceObConfig.dependencies.hars.length, 391 ); 392 const mergedConfigs = newObConfigResolver.getMergedConfigsForTest(selfConfig, dependencyConfigs); 393 newObConfigResolver.handleReservedArrayForTest(mergedConfigs); 394 let needKeepSystemApi = enableObfuscation && 395 (mergedConfigs.options.enablePropertyObfuscation || 396 (mergedConfigs.options.enableExportObfuscation && mergedConfigs.options.enableToplevelObfuscation)); 397 398 newObConfigResolver.getDependencyConfigsForTest(sourceObConfig, dependencyConfigs); 399 400 expect(needConsumerConfigs).to.be.true; 401 expect(!dependencyMaxLength).to.be.false; 402 expect(needDependencyConfigs).to.be.true; 403 expect(dependencyConfigs).to.deep.equal(new MergedConfig()); 404 expect(enableObfuscation).to.be.true; 405 expect(needKeepSystemApi).to.be.false; 406 expect(needConsumerConfigs).to.be.true; 407 }); 408 409 it('should handle the case when enableObfuscation is true', () => { 410 testClass.sourceObConfig = { 411 selfConfig: { 412 ruleOptions: { enable: true }, 413 consumerRules: ['./test/testData/obfuscation/keepDts/obfuscation-template.txt'], 414 }, 415 dependencies: { libraries: [], hars: [] }, 416 obfuscationCacheDir: './test/testData/cache', 417 options: { 418 disableObfuscation: true 419 } 420 }; 421 testClass.isHarCompiled = true; 422 testClass.performancePrinter = {}; 423 let enableObfuscation = testClass.sourceObConfig.selfConfig.ruleOptions.enable; 424 let selfConfig = new MergedConfig(); 425 newObConfigResolver.getSelfConfigsForTest(selfConfig); 426 enableObfuscation = !selfConfig.options.disableObfuscation; 427 enableObfuscation = false; 428 let needConsumerConfigs = testClass.isHarCompiled && testClass.sourceObConfig.selfConfig.consumerRules && 429 testClass.sourceObConfig.selfConfig.consumerRules.length > 0; 430 let needDependencyConfigs = enableObfuscation || needConsumerConfigs; 431 let dependencyConfigs = new MergedConfig(); 432 const dependencyMaxLength = Math.max( 433 testClass.sourceObConfig.dependencies.libraries.length, 434 testClass.sourceObConfig.dependencies.hars.length, 435 testClass.sourceObConfig.dependencies.hsps?.length ?? 0, 436 testClass.sourceObConfig.dependencies.hspLibraries?.length ?? 0 437 ); 438 newObConfigResolver.getDependencyConfigsForTest(testClass.sourceObConfig, dependencyConfigs); 439 440 expect(needConsumerConfigs).to.be.true; 441 expect(!dependencyMaxLength).to.be.true; 442 expect(needDependencyConfigs).to.be.true; 443 expect(dependencyConfigs).to.deep.equal(new MergedConfig()); 444 expect(enableObfuscation).to.be.false; 445 }); 446 }); 447 448 describe('getSelfConfigs', () => { 449 it('should create an instance with the correct properties', () => { 450 const projectConfig = { 451 obfuscationOptions: { 452 selfConfig: { 453 ruleOptions: { 454 rules: [] 455 } 456 } 457 }, 458 compileHar: true 459 }; 460 const isTerser = false; 461 const resolver = new ObConfigResolver(projectConfig, printObfLogger, isTerser); 462 463 expect(resolver).to.be.an('object'); 464 expect(resolver.sourceObConfig).to.deep.equal(projectConfig.obfuscationOptions); 465 expect(resolver.isHarCompiled).to.equal(projectConfig.compileHar); 466 expect(resolver.isTerser).to.equal(isTerser); 467 }); 468 469 it('should create an instance with the correct properties', () => { 470 const projectConfig = { 471 obfuscationOptions: { 472 selfConfig: { 473 ruleOptions: { 474 rules: ['./test/ut/initialization/tempNameCache.json'] 475 } 476 } 477 }, 478 compileHar: true 479 }; 480 const isTerser = false; 481 const resolver = new ObConfigResolver(projectConfig, printObfLogger, isTerser); 482 483 expect(resolver).to.be.an('object'); 484 expect(resolver.sourceObConfig).to.deep.equal(projectConfig.obfuscationOptions); 485 expect(resolver.isHarCompiled).to.equal(projectConfig.compileHar); 486 expect(resolver.isTerser).to.equal(isTerser); 487 }); 488 489 it('should get self configs correctly', () => { 490 const projectConfig = { 491 obfuscationOptions: { 492 selfConfig: { 493 ruleOptions: { 494 rules: ['./test/ut/initialization/tempNameCache.json'] 495 } 496 } 497 }, 498 compileHar: true 499 }; 500 const isTerser = false; 501 const resolver = new ObConfigResolver(projectConfig, printObfLogger, isTerser); 502 const selfConfigs = new MergedConfig(); 503 504 resolver.getSelfConfigsForTest(selfConfigs); 505 506 expect(resolver).to.be.an('object'); 507 expect(resolver.sourceObConfig).to.deep.equal(projectConfig.obfuscationOptions); 508 expect(resolver.isHarCompiled).to.equal(projectConfig.compileHar); 509 expect(resolver.isTerser).to.equal(isTerser); 510 }); 511 }); 512 513 describe('getConfigByPath', () => { 514 const projectConfig = { 515 obfuscationOptions: { 516 selfConfig: { 517 ruleOptions: { 518 rules: ['./test/testData/obfuscation/filename_obf/getConfigByPath.json'] 519 } 520 } 521 }, 522 compileHar: true 523 }; 524 let sandbox; 525 let instance; 526 527 beforeEach(() => { 528 sandbox = sinon.createSandbox(); 529 instance = new ObConfigResolver(projectConfig, printObfLogger, true); 530 instance.logger = { error: sandbox.stub() }; 531 }); 532 533 afterEach(() => { 534 sandbox.restore(); 535 }); 536 537 it('should read file content and handle config content', () => { 538 const path = './test/testData/obfuscation/filename_obf/getConfigByPath.json'; 539 let fileContent; 540 const expectedContent = '{"key": "value"}'; 541 const configs = new MergedConfig(); 542 543 fileContent = fs.readFileSync(path, 'utf-8'); 544 instance.getConfigByPathForTest(path, configs); 545 instance.handleConfigContent(fileContent, configs, path); 546 547 expect(fileContent).to.equal(expectedContent); 548 expect(configs).to.be.an.instanceOf(MergedConfig); 549 }); 550 551 it('should log error and throw when failed to open file', () => { 552 const path = './test/testData/obfuscation/filename_obf/non-existent-file.json'; 553 const configs = new MergedConfig(); 554 const stub = sinon.stub(console, 'error'); 555 const errorMessage = `Failed to open ${path}. Error message: Error: ENOENT: no such file or directory, open ${path}`; 556 sandbox.stub(fs, 'readFileSync').throws(new Error(`ENOENT: no such file or directory, open ${path}`)); 557 try { 558 instance.getConfigByPath(path, configs); 559 } catch (err) { 560 } 561 expect(stub.calledWith(errorMessage)).to.be.true; 562 stub.restore(); 563 }); 564 565 it('should log error and throw when failed to open file with hvigor errorCode', () => { 566 const path = './test/testData/obfuscation/filename_obf/non-existent-file.json'; 567 const configs = new MergedConfig(); 568 const stub = sinon.stub(console, 'error'); 569 const errorMessage = { 570 code: '10804001', 571 description: 'ArkTS compiler Error', 572 cause: `Failed to open obfuscation config file from ${path}. Error message: Error: ENOENT: no such file or directory, open ${path}`, 573 position: path, 574 solutions: [`Please check whether ${path} exists.`], 575 }; 576 instance = new ObConfigResolver(projectConfig, printObfHvigorLogger, true); 577 sandbox.stub(fs, 'readFileSync').throws(new Error(`ENOENT: no such file or directory, open ${path}`)); 578 try { 579 instance.getConfigByPath(path, configs); 580 } catch (err) { 581 } 582 expect(stub.calledWith(errorMessage)).to.be.true; 583 stub.restore(); 584 }); 585 }); 586 587 it('should return a new MergedConfig instance when sourceObConfig is not defined', function() { 588 const projectConfig = { 589 sourceObConfig: null, 590 getMergedConfig: function() { 591 let sourceObConfig = this.sourceObConfig; 592 if (!sourceObConfig) { 593 return new MergedConfig(); 594 } 595 } 596 }; 597 598 const result = projectConfig.getMergedConfig(); 599 expect(result).to.be.an.instanceOf(MergedConfig); 600 }); 601 602 describe('resolveKeepConfig', () => { 603 it('should resolve keep config correctly, starts with "!" and contains "*", not starts with "!"', () => { 604 const keepConfigs = ['!test/*/exclude.js', 'test/include.js']; 605 const configs = new MergedConfig(); 606 const configPath = './test/testData/obfuscation/keepDts/obfuscation-template.txt'; 607 608 newObConfigResolver.resolveKeepConfig(keepConfigs, configs, configPath); 609 610 expect(configs.excludeUniversalPaths).to.have.lengthOf(1); 611 expect(configs.keepUniversalPaths).to.have.lengthOf(0); 612 expect(configs.excludePathSet).to.have.lengthOf(0); 613 expect(configs.keepSourceOfPaths).to.have.lengthOf(0); 614 }); 615 616 it('should resolve keep config correctly, starts with "!" and contains "*", not starts with "!" and "?"', () => { 617 const keepConfigs = ['!test/*/exclude.js', 'test/?/include.js']; 618 const configs = new MergedConfig(); 619 const configPath = './test/testData/obfuscation/keepDts/obfuscation-template.txt'; 620 621 newObConfigResolver.resolveKeepConfig(keepConfigs, configs, configPath); 622 623 expect(configs.excludeUniversalPaths).to.have.lengthOf(1); 624 expect(configs.keepUniversalPaths).to.have.lengthOf(1); 625 expect(configs.excludePathSet).to.have.lengthOf(0); 626 expect(configs.keepSourceOfPaths).to.have.lengthOf(0); 627 }); 628 629 it('should resolve keep config correctly, both start with "!", contains "*" and "?"', () => { 630 const keepConfigs = ['!test/*/exclude.js', '!test/?/include.js']; 631 const configs = new MergedConfig(); 632 const configPath = './test/testData/obfuscation/keepDts/obfuscation-template.txt'; 633 634 newObConfigResolver.resolveKeepConfig(keepConfigs, configs, configPath); 635 636 expect(configs.excludeUniversalPaths).to.have.lengthOf(2); 637 expect(configs.keepUniversalPaths).to.have.lengthOf(0); 638 expect(configs.excludePathSet).to.have.lengthOf(0); 639 expect(configs.keepSourceOfPaths).to.have.lengthOf(0); 640 }); 641 642 it('should resolve keep config correctly, not starts with "!" and contains "*" and "?"', () => { 643 const keepConfigs = ['test/*/exclude.js', 'test/?/include.js']; 644 const configs = new MergedConfig(); 645 const configPath = './test/testData/obfuscation/keepDts/obfuscation-template.txt'; 646 647 newObConfigResolver.resolveKeepConfig(keepConfigs, configs, configPath); 648 649 expect(configs.excludeUniversalPaths).to.have.lengthOf(0); 650 expect(configs.keepUniversalPaths).to.have.lengthOf(2); 651 expect(configs.excludePathSet).to.have.lengthOf(0); 652 expect(configs.keepSourceOfPaths).to.have.lengthOf(0); 653 }); 654 655 it('should resolve keep config correctly, starts with "!", not starts with "!" and contains "*"', () => { 656 const keepConfigs = ['!test/exclude.js', 'test/*/include.js']; 657 const configs = new MergedConfig(); 658 const configPath = './test/testData/obfuscation/keepDts/obfuscation-template.txt'; 659 660 newObConfigResolver.resolveKeepConfig(keepConfigs, configs, configPath); 661 662 expect(configs.excludeUniversalPaths).to.have.lengthOf(0); 663 expect(configs.keepUniversalPaths).to.have.lengthOf(1); 664 expect(configs.excludePathSet).to.have.lengthOf(1); 665 expect(configs.keepSourceOfPaths).to.have.lengthOf(0); 666 }); 667 668 it('should resolve keep config correctly, starts with "!" and not starts with "!"', () => { 669 const keepConfigs = ['!test/exclude.js', 'test/include.js']; 670 const configs = new MergedConfig(); 671 const configPath = './test/testData/obfuscation/keepDts/obfuscation-template.txt'; 672 673 newObConfigResolver.resolveKeepConfig(keepConfigs, configs, configPath); 674 675 expect(configs.excludeUniversalPaths).to.have.lengthOf(0); 676 expect(configs.keepUniversalPaths).to.have.lengthOf(0); 677 expect(configs.excludePathSet).to.have.lengthOf(1); 678 expect(configs.keepSourceOfPaths).to.have.lengthOf(0); 679 }); 680 681 it('should resolve keep config correctly, both start with "!"', () => { 682 const keepConfigs = ['!test/exclude.js', '!test/include.js']; 683 const configs = new MergedConfig(); 684 const configPath = './test/testData/obfuscation/keepDts/obfuscation-template.txt'; 685 686 newObConfigResolver.resolveKeepConfig(keepConfigs, configs, configPath); 687 688 expect(configs.excludeUniversalPaths).to.have.lengthOf(0); 689 expect(configs.keepUniversalPaths).to.have.lengthOf(0); 690 expect(configs.excludePathSet).to.have.lengthOf(2); 691 expect(configs.keepSourceOfPaths).to.have.lengthOf(0); 692 }); 693 }); 694 695 describe('resolvePath', () => { 696 it('should return the absolute path if token is already an absolute path', () => { 697 const configPath = '/home/user/config.json'; 698 const token = '/home/user/data.txt'; 699 const result = newObConfigResolver.resolvePathForTest(configPath, token); 700 expect(result).to.equal(token); 701 }); 702 703 it('should resolve the relative path based on the config file directory', () => { 704 const configPath = '/home/user/config.json'; 705 const token = 'data.txt'; 706 const expectedResult = '/home/user/data.txt'; 707 const result = newObConfigResolver.resolvePathForTest(configPath, token); 708 expect(result).to.equal(expectedResult); 709 }); 710 }); 711 712 describe('getTokenType', () => { 713 it('should return the correct OptionType for each token', () => { 714 const tokens = [ 715 ObConfigResolver.KEEP_DTS, 716 ObConfigResolver.KEEP_GLOBAL_NAME, 717 ObConfigResolver.KEEP_PROPERTY_NAME, 718 ObConfigResolver.KEEP_FILE_NAME, 719 ObConfigResolver.KEEP_COMMENTS, 720 ObConfigResolver.DISABLE_OBFUSCATION, 721 ObConfigResolver.ENABLE_PROPERTY_OBFUSCATION, 722 ObConfigResolver.ENABLE_STRING_PROPERTY_OBFUSCATION, 723 ObConfigResolver.ENABLE_TOPLEVEL_OBFUSCATION, 724 ObConfigResolver.ENABLE_FILENAME_OBFUSCATION, 725 ObConfigResolver.ENABLE_EXPORT_OBFUSCATION, 726 ObConfigResolver.ENABLE_LIB_OBFUSCATION_OPTIONS, 727 ObConfigResolver.REMOVE_COMMENTS, 728 ObConfigResolver.COMPACT, 729 ObConfigResolver.REMOVE_LOG, 730 ObConfigResolver.PRINT_NAMECACHE, 731 ObConfigResolver.PRINT_KEPT_NAMES, 732 ObConfigResolver.APPLY_NAMECACHE, 733 ObConfigResolver.KEEP, 734 ObConfigResolver.EXTRA_OPTIONS, 735 ObConfigResolver.STRIP_LANGUAGE_DEFAULT, 736 ObConfigResolver.STRIP_SYSTEM_API_ARGS, 737 'unknown_token' 738 ]; 739 740 const expectedResults = [ 741 OptionTypeForTest.KEEP_DTS, 742 OptionTypeForTest.KEEP_GLOBAL_NAME, 743 OptionTypeForTest.KEEP_PROPERTY_NAME, 744 OptionTypeForTest.KEEP_FILE_NAME, 745 OptionTypeForTest.KEEP_COMMENTS, 746 OptionTypeForTest.DISABLE_OBFUSCATION, 747 OptionTypeForTest.ENABLE_PROPERTY_OBFUSCATION, 748 OptionTypeForTest.ENABLE_STRING_PROPERTY_OBFUSCATION, 749 OptionTypeForTest.ENABLE_TOPLEVEL_OBFUSCATION, 750 OptionTypeForTest.ENABLE_FILENAME_OBFUSCATION, 751 OptionTypeForTest.ENABLE_EXPORT_OBFUSCATION, 752 OptionTypeForTest.ENABLE_LIB_OBFUSCATION_OPTIONS, 753 OptionTypeForTest.REMOVE_COMMENTS, 754 OptionTypeForTest.COMPACT, 755 OptionTypeForTest.REMOVE_LOG, 756 OptionTypeForTest.PRINT_NAMECACHE, 757 OptionTypeForTest.PRINT_KEPT_NAMES, 758 OptionTypeForTest.APPLY_NAMECACHE, 759 OptionTypeForTest.KEEP, 760 OptionTypeForTest.EXTRA_OPTIONS, 761 OptionTypeForTest.STRIP_LANGUAGE_DEFAULT, 762 OptionTypeForTest.STRIP_SYSTEM_API_ARGS, 763 OptionTypeForTest.NONE 764 ]; 765 766 for (let i = 0; i < tokens.length; i++) { 767 const result = newObConfigResolver.getTokenTypeForTest(tokens[i]); 768 expect(result).to.equal(expectedResults[i]); 769 } 770 }); 771 }); 772 773 describe('handleConfigContent', () => { 774 it('should handle config content correctly', () => { 775 const configs: MergedConfig = new MergedConfig(); 776 configs.options = new ObOptionsForTest(); 777 778 const configPath = './test/testData/obfuscation/keepDts/obfuscation-template.txt'; 779 const data = ` 780 #This is a comment 781 -none, 782 -keep obfuscation-template.txt, 783 -keep-dts, 784 -keep-global-name, 785 -keep-property-name, 786 -keep-file-name, 787 -keep-comments, 788 -disable-obfuscation, 789 -enable-property-obfuscation, 790 -enable-string-property-obfuscation, 791 -enable-toplevel-obfuscation, 792 -enable-filename-obfuscation, 793 -enable-export-obfuscation, 794 -enable-lib-obfuscation-options, 795 -use-keep-in-source, 796 -extra-options strip-language-default, 797 -extra-options strip-system-api-args, 798 -keep-parameter-names 799 -remove-comments, 800 -compact, 801 -remove-log, 802 -print-namecache obfuscation-template.txt, 803 -print-kept-names, 804 -apply-namecache obfuscation-template.txt 805 `; 806 807 newObConfigResolver.handleConfigContentForTest(data, configs, configPath); 808 809 expect(configs.options.disableObfuscation).to.be.true; 810 expect(configs.options.enablePropertyObfuscation).to.be.true; 811 expect(configs.options.enableStringPropertyObfuscation).to.be.true; 812 expect(configs.options.enableToplevelObfuscation).to.be.true; 813 expect(configs.options.removeComments).to.be.true; 814 expect(configs.options.enableFileNameObfuscation).to.be.true; 815 expect(configs.options.enableExportObfuscation).to.be.true; 816 expect(configs.options.enableLibObfuscationOptions).to.be.true; 817 expect(configs.options.enableAtKeep).to.be.true; 818 expect(configs.options.compact).to.be.true; 819 expect(configs.options.removeLog).to.be.true; 820 expect(configs.options.stripLanguageDefault).to.be.true; 821 expect(configs.options.stripSystemApiArgs).to.be.true; 822 expect(configs.options.keepParameterNames).to.be.true; 823 }); 824 825 it('should handle config content correctly when diffenent combinations use line break splitting', () => { 826 const configs: MergedConfig = new MergedConfig(); 827 configs.options = new ObOptionsForTest(); 828 829 const configPath = './test/testData/obfuscation/keepDts/obfuscation-template.txt'; 830 const data = ` 831 #This is a comment 832 -extra-options 833 strip-language-default 834 -extra-options 835 strip-system-api-args 836 `; 837 838 newObConfigResolver.handleConfigContentForTest(data, configs, configPath); 839 840 expect(configs.options.stripLanguageDefault).to.be.true; 841 expect(configs.options.stripSystemApiArgs).to.be.true; 842 }); 843 844 it('should handle config content correctly when diffenent combinations use line break splitting', () => { 845 const configs: MergedConfig = new MergedConfig(); 846 configs.options = new ObOptionsForTest(); 847 848 const configPath = './test/testData/obfuscation/keepDts/obfuscation-template.txt'; 849 const data = ` 850 #This is a comment 851 -extra-options strip-language-default 852 -extra-options strip-system-api-args 853 `; 854 855 newObConfigResolver.handleConfigContentForTest(data, configs, configPath); 856 857 expect(configs.options.stripLanguageDefault).to.be.true; 858 expect(configs.options.stripSystemApiArgs).to.be.true; 859 }); 860 861 it('should handle config content correctly when diffenent combinations use space separation', () => { 862 const configs: MergedConfig = new MergedConfig(); 863 configs.options = new ObOptionsForTest(); 864 865 const configPath = './test/testData/obfuscation/keepDts/obfuscation-template.txt'; 866 const data = ` 867 #This is a comment 868 -extra-options strip-language-default -extra-options strip-system-api-args 869 `; 870 871 newObConfigResolver.handleConfigContentForTest(data, configs, configPath); 872 873 expect(configs.options.stripLanguageDefault).to.be.true; 874 expect(configs.options.stripSystemApiArgs).to.be.true; 875 }); 876 877 it('should handle config content correctly when diffenent combinations only use one "-extra-options"', () => { 878 const configs: MergedConfig = new MergedConfig(); 879 configs.options = new ObOptionsForTest(); 880 881 const configPath = './test/testData/obfuscation/keepDts/obfuscation-template.txt'; 882 const data = ` 883 #This is a comment 884 -extra-options strip-language-default, strip-system-api-args 885 `; 886 887 newObConfigResolver.handleConfigContentForTest(data, configs, configPath); 888 889 expect(configs.options.stripLanguageDefault).to.be.true; 890 expect(configs.options.stripSystemApiArgs).to.be.true; 891 }); 892 893 it('should handle config content correctly when no "-extra-options"', () => { 894 const configs: MergedConfig = new MergedConfig(); 895 configs.options = new ObOptionsForTest(); 896 897 const configPath = './test/testData/obfuscation/keepDts/obfuscation-template.txt'; 898 const data = ` 899 #This is a comment 900 strip-language-default, strip-system-api-args 901 `; 902 903 newObConfigResolver.handleConfigContentForTest(data, configs, configPath); 904 905 expect(configs.options.stripLanguageDefault).to.be.false; 906 expect(configs.options.stripSystemApiArgs).to.be.false; 907 }); 908 909 it('should handle config content correctly when have invalid token between "-extra-options" and "strip-language-default"', () => { 910 const configs: MergedConfig = new MergedConfig(); 911 configs.options = new ObOptionsForTest(); 912 913 const configPath = './test/testData/obfuscation/keepDts/obfuscation-template.txt'; 914 const data = ` 915 #This is a comment 916 -extra-options 917 invalid-token 918 strip-system-api-args 919 strip-language-default 920 `; 921 922 newObConfigResolver.handleConfigContentForTest(data, configs, configPath); 923 924 expect(configs.options.stripLanguageDefault).to.be.false; 925 expect(configs.options.stripSystemApiArgs).to.be.false; 926 }); 927 928 it('should handle config content correctly when have valid token between "-extra-options" and "strip-language-default"', () => { 929 const configs: MergedConfig = new MergedConfig(); 930 configs.options = new ObOptionsForTest(); 931 932 const configPath = './test/testData/obfuscation/keepDts/obfuscation-template.txt'; 933 const data = ` 934 #This is a comment 935 -extra-options 936 -enable-property-obfuscation 937 strip-language-default 938 strip-system-api-args 939 `; 940 941 newObConfigResolver.handleConfigContentForTest(data, configs, configPath); 942 943 expect(configs.options.enablePropertyObfuscation).to.be.true; 944 expect(configs.options.stripLanguageDefault).to.be.false; 945 expect(configs.options.stripSystemApiArgs).to.be.false; 946 }); 947 948 it('should handle config content correctly when enable lib obfuscation options', () => { 949 const configs: MergedConfig = new MergedConfig(); 950 configs.options = new ObOptionsForTest(); 951 952 const configPath = './test/testData/obfuscation/enable_lib_obfuscation_options/obfuscation-rule.txt'; 953 const data = fs.readFileSync(configPath, 'utf-8'); 954 955 newObConfigResolver.handleConfigContentForTest(data, configs, configPath); 956 957 expect(configs.options.enableLibObfuscationOptions).to.be.true; 958 }); 959 }); 960 961 describe('1: test Api collectSystemApiWhitelist', function() { 962 it('1-1: test collectSystemApiWhitelist: -enable-property-obfuscation', function () { 963 let obfuscationCacheDir = path.join(OBFUSCATE_TESTDATA_DIR, 'property'); 964 let obfuscationOptions = { 965 'selfConfig': { 966 'ruleOptions': { 967 'enable': true, 968 'rules': [ 969 path.join(OBFUSCATE_TESTDATA_DIR, 'property/property.txt') 970 ] 971 }, 972 'consumerRules': [], 973 }, 974 'dependencies': { 975 'libraries': [], 976 'hars': [] 977 }, 978 'obfuscationCacheDir': obfuscationCacheDir, 979 'sdkApis': [ 980 path.join(OBFUSCATE_TESTDATA_DIR, 'system_api.d.ts') 981 ] 982 }; 983 let projectConfig = { 984 obfuscationOptions, 985 compileHar: false 986 }; 987 const obConfig: ObConfigResolver = new ObConfigResolver(projectConfig, undefined); 988 obConfig.resolveObfuscationConfigs(); 989 const reservedSdkApiForProp = UnobfuscationCollections.reservedSdkApiForProp; 990 const reservedSdkApiForGlobal = UnobfuscationCollections.reservedSdkApiForGlobal; 991 const reservedSdkApiForLocal = UnobfuscationCollections.reservedSdkApiForLocal; 992 993 expect(reservedSdkApiForProp.size == 12).to.be.true; 994 expect(reservedSdkApiForProp.has('TestClass')).to.be.true; 995 expect(reservedSdkApiForProp.has('para1')).to.be.true; 996 expect(reservedSdkApiForProp.has('para2')).to.be.true; 997 expect(reservedSdkApiForProp.has('foo')).to.be.true; 998 expect(reservedSdkApiForProp.has('TestFunction')).to.be.true; 999 expect(reservedSdkApiForProp.has('funcPara1')).to.be.true; 1000 expect(reservedSdkApiForProp.has('funcPara2')).to.be.true; 1001 expect(reservedSdkApiForProp.has('ns')).to.be.true; 1002 expect(reservedSdkApiForProp.has('NavigationBuilderRegister')).to.be.true; 1003 expect(reservedSdkApiForProp.has('ViewV2')).to.be.true; 1004 expect(reservedSdkApiForProp.has('initParam')).to.be.true; 1005 expect(reservedSdkApiForProp.has('updateParam')).to.be.true; 1006 expect(reservedSdkApiForProp.has('NavigationBuilderRegister')).to.be.true; 1007 expect(reservedSdkApiForProp.has('__Recycle__')).to.be.false; 1008 expect(reservedSdkApiForGlobal.size === 0).to.be.true; 1009 expect(reservedSdkApiForLocal.size === 8).to.be.true; 1010 UnobfuscationCollections.clear(); 1011 1012 let systemApiPath = obfuscationCacheDir + '/systemApiCache.json'; 1013 const data = fs.readFileSync(systemApiPath, 'utf8'); 1014 const systemApiContent = JSON.parse(data); 1015 1016 expect(systemApiContent.ReservedPropertyNames.length == 12).to.be.true; 1017 expect(systemApiContent.ReservedPropertyNames.includes('TestClass')).to.be.true; 1018 expect(systemApiContent.ReservedPropertyNames.includes('para1')).to.be.true; 1019 expect(systemApiContent.ReservedPropertyNames.includes('para2')).to.be.true; 1020 expect(systemApiContent.ReservedPropertyNames.includes('foo')).to.be.true; 1021 expect(systemApiContent.ReservedPropertyNames.includes('TestFunction')).to.be.true; 1022 expect(systemApiContent.ReservedPropertyNames.includes('funcPara1')).to.be.true; 1023 expect(systemApiContent.ReservedPropertyNames.includes('funcPara2')).to.be.true; 1024 expect(systemApiContent.ReservedPropertyNames.includes('ns')).to.be.true; 1025 expect(systemApiContent.ReservedPropertyNames.includes('NavigationBuilderRegister')).to.be.true; 1026 expect(systemApiContent.ReservedPropertyNames.includes('ViewV2')).to.be.true; 1027 expect(systemApiContent.ReservedPropertyNames.includes('initParam')).to.be.true; 1028 expect(systemApiContent.ReservedPropertyNames.includes('updateParam')).to.be.true; 1029 expect(systemApiContent.ReservedPropertyNames.includes('NavigationBuilderRegister')).to.be.true; 1030 expect(systemApiContent.ReservedPropertyNames.includes('__Recycle__')).to.be.false; 1031 expect(systemApiContent.ReservedGlobalNames === undefined).to.be.true; 1032 expect(systemApiContent.ReservedLocalNames.size === 8).to.be.false; 1033 1034 fs.unlinkSync(systemApiPath); 1035 }); 1036 1037 it('1-2: test collectSystemApiWhitelist: -enable-export-obfuscation', function () { 1038 let obfuscationCacheDir = path.join(OBFUSCATE_TESTDATA_DIR, 'export'); 1039 let obfuscationOptions = { 1040 'selfConfig': { 1041 'ruleOptions': { 1042 'enable': true, 1043 'rules': [ 1044 path.join(OBFUSCATE_TESTDATA_DIR, 'export/export.txt') 1045 ] 1046 }, 1047 'consumerRules': [], 1048 }, 1049 'dependencies': { 1050 'libraries': [], 1051 'hars': [] 1052 }, 1053 'obfuscationCacheDir': obfuscationCacheDir, 1054 'sdkApis': [ 1055 path.join(OBFUSCATE_TESTDATA_DIR, 'system_api.d.ts') 1056 ] 1057 }; 1058 let projectConfig = { 1059 obfuscationOptions, 1060 compileHar: false 1061 }; 1062 const obConfig: ObConfigResolver = new ObConfigResolver(projectConfig, undefined); 1063 obConfig.resolveObfuscationConfigs(); 1064 const reservedSdkApiForProp = UnobfuscationCollections.reservedSdkApiForProp; 1065 const reservedSdkApiForGlobal = UnobfuscationCollections.reservedSdkApiForGlobal; 1066 1067 expect(reservedSdkApiForProp.size == 0).to.be.true; 1068 expect(reservedSdkApiForGlobal.size == 0).to.be.true; 1069 UnobfuscationCollections.clear(); 1070 1071 let systemApiPath = obfuscationCacheDir + '/systemApiCache.json'; 1072 const noSystemApi = fs.existsSync(systemApiPath); 1073 1074 expect(noSystemApi).to.be.false; 1075 }); 1076 1077 it('1-3: test collectSystemApiWhitelist: -enable-export-obfuscation -enable-toplevel-obfuscation', function () { 1078 let obfuscationCacheDir = path.join(OBFUSCATE_TESTDATA_DIR, 'export_toplevel'); 1079 let obfuscationOptions = { 1080 'selfConfig': { 1081 'ruleOptions': { 1082 'enable': true, 1083 'rules': [ 1084 path.join(OBFUSCATE_TESTDATA_DIR, 'export_toplevel/export_toplevel.txt') 1085 ] 1086 }, 1087 'consumerRules': [], 1088 }, 1089 'dependencies': { 1090 'libraries': [], 1091 'hars': [] 1092 }, 1093 'obfuscationCacheDir': obfuscationCacheDir, 1094 'sdkApis': [ 1095 path.join(OBFUSCATE_TESTDATA_DIR, 'system_api.d.ts') 1096 ] 1097 }; 1098 let projectConfig = { 1099 obfuscationOptions, 1100 compileHar: false 1101 }; 1102 const obConfig: ObConfigResolver = new ObConfigResolver(projectConfig, undefined); 1103 obConfig.resolveObfuscationConfigs(); 1104 const reservedSdkApiForProp = UnobfuscationCollections.reservedSdkApiForProp; 1105 const reservedSdkApiForGlobal = UnobfuscationCollections.reservedSdkApiForGlobal; 1106 1107 expect(reservedSdkApiForProp.size == 0).to.be.true; 1108 expect(reservedSdkApiForGlobal.size == 3).to.be.true; 1109 expect(reservedSdkApiForGlobal.has('TestClass')).to.be.true; 1110 expect(reservedSdkApiForGlobal.has('TestFunction')).to.be.true; 1111 expect(reservedSdkApiForGlobal.has('ns')).to.be.true; 1112 UnobfuscationCollections.clear(); 1113 1114 let systemApiPath = obfuscationCacheDir + '/systemApiCache.json'; 1115 const data = fs.readFileSync(systemApiPath, 'utf8'); 1116 const systemApiContent = JSON.parse(data); 1117 1118 expect(systemApiContent.ReservedPropertyNames == undefined).to.be.true; 1119 expect(systemApiContent.ReservedGlobalNames.length == 3).to.be.true; 1120 expect(systemApiContent.ReservedGlobalNames.includes('TestClass')).to.be.true; 1121 expect(systemApiContent.ReservedGlobalNames.includes('TestFunction')).to.be.true; 1122 expect(systemApiContent.ReservedGlobalNames.includes('ns')).to.be.true; 1123 1124 fs.unlinkSync(systemApiPath); 1125 }); 1126 1127 it('1-4: test collectSystemApiWhitelist: system api when -enable-property-obfuscation and -extra-options strip-system-api-args', function () { 1128 let obfuscationCacheDir = path.join(OBFUSCATE_TESTDATA_DIR, 'system_api_optimize'); 1129 let obfuscationOptions = { 1130 'selfConfig': { 1131 'ruleOptions': { 1132 'enable': true, 1133 'rules': [ 1134 path.join(OBFUSCATE_TESTDATA_DIR, 'system_api_optimize/system_api_optimize.txt') 1135 ] 1136 }, 1137 'consumerRules': [], 1138 }, 1139 'dependencies': { 1140 'libraries': [], 1141 'hars': [] 1142 }, 1143 'obfuscationCacheDir': obfuscationCacheDir, 1144 'sdkApis': [ 1145 path.join(OBFUSCATE_TESTDATA_DIR, 'system_api.d.ts') 1146 ] 1147 }; 1148 let projectConfig = { 1149 obfuscationOptions, 1150 compileHar: false 1151 }; 1152 const obConfig: ObConfigResolver = new ObConfigResolver(projectConfig, undefined); 1153 obConfig.resolveObfuscationConfigs(); 1154 const reservedSdkApiForProp = UnobfuscationCollections.reservedSdkApiForProp; 1155 const reservedSdkApiForGlobal = UnobfuscationCollections.reservedSdkApiForGlobal; 1156 const reservedSdkApiForLocal = UnobfuscationCollections.reservedSdkApiForLocal; 1157 1158 expect(reservedSdkApiForProp.has('TestClass')).to.be.true; 1159 expect(reservedSdkApiForProp.has('para1')).to.be.true; 1160 expect(reservedSdkApiForProp.has('para2')).to.be.true; 1161 expect(reservedSdkApiForProp.has('foo')).to.be.true; 1162 expect(reservedSdkApiForProp.has('TestFunction')).to.be.true; 1163 expect(reservedSdkApiForProp.has('funcPara1')).to.be.false; 1164 expect(reservedSdkApiForProp.has('funcPara2')).to.be.false; 1165 expect(reservedSdkApiForProp.has('ns')).to.be.true; 1166 expect(reservedSdkApiForProp.has('NavigationBuilderRegister')).to.be.true; 1167 expect(reservedSdkApiForProp.has('__Recycle__')).to.be.true; 1168 expect(reservedSdkApiForGlobal.size == 0).to.be.true; 1169 expect(reservedSdkApiForLocal.size == 0).to.be.true; 1170 UnobfuscationCollections.clear(); 1171 1172 let systemApiPath = obfuscationCacheDir + '/systemApiCache.json'; 1173 const data = fs.readFileSync(systemApiPath, 'utf8'); 1174 const systemApiContent = JSON.parse(data); 1175 1176 expect(systemApiContent.ReservedPropertyNames.includes('TestClass')).to.be.true; 1177 expect(systemApiContent.ReservedPropertyNames.includes('para1')).to.be.true; 1178 expect(systemApiContent.ReservedPropertyNames.includes('para2')).to.be.true; 1179 expect(systemApiContent.ReservedPropertyNames.includes('foo')).to.be.true; 1180 expect(systemApiContent.ReservedPropertyNames.includes('TestFunction')).to.be.true; 1181 expect(systemApiContent.ReservedPropertyNames.includes('funcPara1')).to.be.false; 1182 expect(systemApiContent.ReservedPropertyNames.includes('funcPara2')).to.be.false; 1183 expect(systemApiContent.ReservedPropertyNames.includes('ns')).to.be.true; 1184 expect(systemApiContent.ReservedPropertyNames.includes('NavigationBuilderRegister')).to.be.true; 1185 expect(systemApiContent.ReservedPropertyNames.includes('__Recycle__')).to.be.true; 1186 expect(systemApiContent.ReservedGlobalNames === undefined).to.be.true; 1187 expect(systemApiContent.ReservedLocalNames === undefined).to.be.true; 1188 1189 fs.unlinkSync(systemApiPath); 1190 }); 1191 }); 1192 }); 1193 1194 describe('getMergedConfigs', function() { 1195 it('should merge all configs', () => { 1196 const config1 = new MergedConfig(); 1197 config1.options.enableLibObfuscationOptions = true; 1198 1199 const config2 = new MergedConfig(); 1200 config2.options.enablePropertyObfuscation = true; 1201 config2.options.enableStringPropertyObfuscation = true; 1202 config2.options.enableToplevelObfuscation = true; 1203 config2.options.compact = true; 1204 config2.options.removeLog = true; 1205 config2.reservedPropertyNames = ['prop2']; 1206 config2.reservedGlobalNames = ['global2']; 1207 config2.keepComments = ['comment2']; 1208 config2.excludePathSet.add('path2'); 1209 1210 const projectConfig = { 1211 obfuscationOptions: { option1: 'value1' }, 1212 compileHar: false 1213 }; 1214 const logger = console; 1215 const isTerser = false; 1216 let newObConfigResolver = new ObConfigResolver(projectConfig, printObfLogger, isTerser); 1217 const res: MergedConfig = newObConfigResolver.getMergedConfigsForTest(config1, config2); 1218 1219 expect(res.options.enablePropertyObfuscation).to.be.true; 1220 expect(res.options.enableStringPropertyObfuscation).to.be.true; 1221 expect(res.options.enableToplevelObfuscation).to.be.true; 1222 expect(res.options.compact).to.be.true; 1223 expect(res.options.removeLog).to.be.true; 1224 expect(res.reservedPropertyNames).to.deep.equal(['prop2']); 1225 expect(res.reservedGlobalNames).to.deep.equal(['global2']); 1226 expect(res.keepComments).to.deep.equal(['comment2']); 1227 expect(res.excludePathSet).to.deep.equal(new Set(['path2'])); 1228 }); 1229 1230 it('should merge only keep configs', () => { 1231 const config1 = new MergedConfig(); 1232 config1.options.enableLibObfuscationOptions = false; 1233 1234 const config2 = new MergedConfig(); 1235 config2.options.enablePropertyObfuscation = true; 1236 config2.options.enableStringPropertyObfuscation = true; 1237 config2.options.enableToplevelObfuscation = true; 1238 config2.options.compact = true; 1239 config2.options.removeLog = true; 1240 config2.reservedPropertyNames = ['prop2']; 1241 config2.reservedGlobalNames = ['global2']; 1242 config2.keepComments = ['comment2']; 1243 config2.excludePathSet.add('path2'); 1244 1245 const projectConfig = { 1246 obfuscationOptions: { option1: 'value1' }, 1247 compileHar: false 1248 }; 1249 const logger = console; 1250 const isTerser = false; 1251 let newObConfigResolver = new ObConfigResolver(projectConfig, printObfLogger, isTerser); 1252 const res: MergedConfig = newObConfigResolver.getMergedConfigsForTest(config1, config2); 1253 1254 expect(res.options.enablePropertyObfuscation).to.be.false; 1255 expect(res.options.enableStringPropertyObfuscation).to.be.false; 1256 expect(res.options.enableToplevelObfuscation).to.be.false; 1257 expect(res.options.compact).to.be.false; 1258 expect(res.options.removeLog).to.be.false; 1259 expect(res.reservedPropertyNames).to.deep.equal(['prop2']); 1260 expect(res.reservedGlobalNames).to.deep.equal(['global2']); 1261 expect(res.keepComments).to.deep.equal(['comment2']); 1262 expect(res.excludePathSet).to.deep.equal(new Set(['path2'])); 1263 }); 1264 }); 1265 1266 describe('genConsumerConfigFilesForTest', function (){ 1267 it('should merge all configs: compileHar is true', () => { 1268 const config1 = new MergedConfig(); 1269 config1.options.enableLibObfuscationOptions = true; 1270 1271 const config2 = new MergedConfig(); 1272 config2.options.enablePropertyObfuscation = true; 1273 config2.options.enableStringPropertyObfuscation = true; 1274 config2.options.enableToplevelObfuscation = true; 1275 config2.options.compact = true; 1276 config2.options.removeLog = true; 1277 config2.reservedPropertyNames = ['prop2']; 1278 config2.reservedGlobalNames = ['global2']; 1279 config2.keepComments = ['comment2']; 1280 config2.excludePathSet.add('path2'); 1281 1282 const projectConfig = { 1283 obfuscationOptions: { option1: 'value1' }, 1284 compileHar: true 1285 }; 1286 const logger = console; 1287 const isTerser = false; 1288 let newObConfigResolver = new ObConfigResolver(projectConfig, printObfLogger, isTerser); 1289 const sourceObConfig: SourceObConfig = { 1290 selfConfig: {} as Obfuscation, 1291 sdkApis: [], 1292 obfuscationCacheDir: '', 1293 exportRulePath: './test/ut/initialization/obfuscation.txt', 1294 dependencies: { 1295 libraries: [], 1296 hars: [], 1297 hsps: [], 1298 hspLibraries: [], 1299 }, 1300 }; 1301 newObConfigResolver.genConsumerConfigFilesForTest(sourceObConfig, config1, config2); 1302 1303 let res: string = fs.readFileSync(sourceObConfig.exportRulePath, 'utf-8'); 1304 expect(res.indexOf('-enable-lib-obfuscation-options') === -1).to.be.true; 1305 expect(res.indexOf('-enable-property-obfuscation') !== -1).to.be.true; 1306 expect(res.indexOf('-enable-string-property-obfuscation') !== -1).to.be.true; 1307 expect(res.indexOf('-enable-toplevel-obfuscation') !== -1).to.be.true; 1308 expect(res.indexOf('-compact') !== -1).to.be.true; 1309 expect(res.indexOf('-remove-log') !== -1).to.be.true; 1310 expect(res.indexOf('-keep-global-name') !== -1).to.be.true; 1311 expect(res.indexOf('global2') !== -1).to.be.true; 1312 expect(res.indexOf('-keep-property-name') !== -1).to.be.true; 1313 expect(res.indexOf('prop2') !== -1).to.be.true; 1314 1315 fs.unlinkSync(sourceObConfig.exportRulePath); 1316 }); 1317 1318 it('should merge all configs: compileHar is false', () => { 1319 const config1 = new MergedConfig(); 1320 config1.options.enableLibObfuscationOptions = false; 1321 1322 const config2 = new MergedConfig(); 1323 config2.options.enablePropertyObfuscation = true; 1324 config2.options.enableStringPropertyObfuscation = true; 1325 config2.options.enableToplevelObfuscation = true; 1326 config2.options.compact = true; 1327 config2.options.removeLog = true; 1328 config2.reservedPropertyNames = ['prop2']; 1329 config2.reservedGlobalNames = ['global2']; 1330 config2.keepComments = ['comment2']; 1331 config2.excludePathSet.add('path2'); 1332 1333 const projectConfig = { 1334 obfuscationOptions: { option1: 'value1' }, 1335 compileHar: false 1336 }; 1337 const logger = console; 1338 const isTerser = false; 1339 let newObConfigResolver = new ObConfigResolver(projectConfig, printObfLogger, isTerser); 1340 const sourceObConfig: SourceObConfig = { 1341 selfConfig: {} as Obfuscation, 1342 sdkApis: [], 1343 obfuscationCacheDir: '', 1344 exportRulePath: './test/ut/initialization/obfuscation.txt', 1345 dependencies: { 1346 libraries: [], 1347 hars: [], 1348 hsps: [], 1349 hspLibraries: [], 1350 }, 1351 }; 1352 newObConfigResolver.genConsumerConfigFilesForTest(sourceObConfig, config1, config2); 1353 1354 let res: string = fs.readFileSync(sourceObConfig.exportRulePath, 'utf-8'); 1355 1356 expect(res.indexOf('-enable-lib-obfuscation-options') === -1).to.be.true; 1357 expect(res.indexOf('-enable-property-obfuscation') === -1).to.be.true; 1358 expect(res.indexOf('-enable-string-property-obfuscation') === -1).to.be.true; 1359 expect(res.indexOf('-enable-toplevel-obfuscation') === -1).to.be.true; 1360 expect(res.indexOf('-compact') === -1).to.be.true; 1361 expect(res.indexOf('-remove-log') === -1).to.be.true; 1362 expect(res.indexOf('-keep-global-name') === -1).to.be.true; 1363 expect(res.indexOf('global2') === -1).to.be.true; 1364 expect(res.indexOf('-keep-property-name') === -1).to.be.true; 1365 expect(res.indexOf('prop2') === -1).to.be.true; 1366 1367 fs.unlinkSync(sourceObConfig.exportRulePath); 1368 }); 1369 }); 1370 1371 describe('collectResevedFileNameInIDEConfig', () => { 1372 let collectPathReservedStringStub; 1373 1374 beforeEach(function() { 1375 collectPathReservedStringStub = sinon.stub(FileUtils, 'collectPathReservedString'); 1376 collectPathReservedStringStub.callsFake((filePath, reservedArray) => reservedArray.push(filePath)); 1377 }); 1378 1379 afterEach(function() { 1380 collectPathReservedStringStub.restore(); 1381 projectConfig.compileShared = false; 1382 projectConfig.byteCodeHar = false; 1383 projectConfig.aceModuleJsonPath = ''; 1384 }); 1385 1386 const ohPackagePath = './test/ut/initialization/testOhPackagePath.json'; 1387 let projectConfig = { 1388 aceModuleJsonPath: '', 1389 projectPath: 'path/to/project', 1390 cachePath: 'path/to/cache', 1391 compileShared: false, 1392 byteCodeHar: false, 1393 aceModuleBuild: 'path/to/build', 1394 } 1395 const entryArray = ['path/to/entry1', 'path/to/entry2']; 1396 const modulePathMap = { 1397 module1: 'path/to/module1', 1398 module2: 'path/to/module2', 1399 }; 1400 1401 it('should collect reserved file names from entryArray and projectConfig', () => { 1402 const result = collectResevedFileNameInIDEConfig('', projectConfig, undefined, entryArray); 1403 expect(result).to.deep.equal(['path/to/entry1', 'path/to/entry2','path/to/project','path/to/cache']); 1404 }); 1405 it('should collect reserved file names from modulePathMap and projectConfig', () => { 1406 projectConfig.compileShared = true; 1407 const result = collectResevedFileNameInIDEConfig('', projectConfig, modulePathMap, []); 1408 expect(result).to.deep.equal(['path/to/module1', 'path/to/module2','module1','module2','path/to/build','etsFortgz','path/to/project','path/to/cache']); 1409 }); 1410 it('should collect reserved file names from ohPackagePath and projectConfig', () => { 1411 projectConfig.byteCodeHar = true; 1412 const result = collectResevedFileNameInIDEConfig(ohPackagePath, projectConfig, undefined, []); 1413 expect(result).to.deep.equal(['path/to/main', 'path/to/types','path/to/build','etsFortgz','path/to/project','path/to/cache']); 1414 }); 1415 it('should collect reserved file names from moduleJsonPath and projectConfig', () => { 1416 projectConfig.aceModuleJsonPath = "./test/ut/initialization/testModuleJsonPath_0.json"; 1417 const hasSrcEntry = collectResevedFileNameInIDEConfig('', projectConfig, undefined, []); 1418 expect(hasSrcEntry).to.deep.equal(['path/to/srcEntry','path/to/project','path/to/cache']); 1419 1420 projectConfig.aceModuleJsonPath = "./test/ut/initialization/testModuleJsonPath_1.json"; 1421 const noSrcEntry = collectResevedFileNameInIDEConfig('', projectConfig, undefined, []); 1422 expect(noSrcEntry).to.deep.equal(['path/to/project','path/to/cache']); 1423 }); 1424 }); 1425 1426 describe('readNameCache', () => { 1427 let tempFilePath; 1428 let testData; 1429 let fsWriteFileSyncStub; 1430 let fsUnlinkSyncStub; 1431 let PropCollections; 1432 let renameFileNameModule; 1433 1434 beforeEach(() => { 1435 PropCollections = { 1436 historyMangledTable: {}, 1437 }; 1438 renameFileNameModule = { 1439 historyFileNameMangledTable: {}, 1440 }; 1441 1442 tempFilePath = './test/ut/initialization/tempNameCache.json'; 1443 testData = { 1444 compileSdkVersion: '1.0.0', 1445 PropertyCache: { key1: 'value1', key2: 'value2' }, 1446 FileNameCache: { key3: 'value3', key4: 'value4' }, 1447 extraKey: '', 1448 }; 1449 1450 fsWriteFileSyncStub = sinon.stub(fs, 'writeFileSync').callsFake((path, data) => {}); 1451 fsUnlinkSyncStub = sinon.stub(fs, 'unlinkSync').callsFake((path) => {}); 1452 }); 1453 1454 afterEach(() => { 1455 fsWriteFileSyncStub.restore(); 1456 fsUnlinkSyncStub.restore(); 1457 }); 1458 1459 it('should read and parse the name cache file correctly', () => { 1460 readNameCache(tempFilePath, printObfLogger); 1461 1462 expect(nameCacheMap.get('extraKey')).to.equal(''); 1463 }); 1464 }); 1465 1466 describe('readNameCache', () => { 1467 let fsReadFileSyncStub; 1468 let logger; 1469 const testPath = './test/ut/initialization/tempNameCache.json'; 1470 1471 beforeEach(() => { 1472 fsReadFileSyncStub = sinon.stub(fs, 'readFileSync').returns('{"compileSdkVersion":"1.0","PropertyCache":{},"FileNameCache":{}}'); 1473 logger = { error: sinon.spy(), printError: (msg)=>{}}; 1474 }); 1475 1476 afterEach(() => { 1477 fsReadFileSyncStub.restore(); 1478 }); 1479 1480 it('should read the name cache file and parse its content', () => { 1481 readNameCache(testPath, printObfLogger); 1482 expect(PropCollections.historyMangledTable).to.deep.equal(new Map()); 1483 expect(renameFileNameModule.historyFileNameMangledTable).to.deep.equal(new Map()); 1484 expect(nameCacheMap.get('compileSdkVersion')).to.be.undefined; 1485 expect(logger.error.called).to.be.false; 1486 }); 1487 1488 it('should handle errors when reading the file', () => { 1489 const mockLogger = { 1490 error: (message: string) => console.error(message), 1491 }; 1492 1493 const nonExistentFilePath = './test/ut/initialization/nonExistentFile.json'; 1494 try { 1495 readNameCache(nonExistentFilePath, printObfLogger); 1496 } catch (err) { 1497 } 1498 expect(logger.error.calledWith(`Failed to open ${nonExistentFilePath}. Error message: Test error`)).to.be.false; 1499 }); 1500 1501 it('should handle errors when reading the file with hvigor errorCode', () => { 1502 const mockLogger = { 1503 error: (message: string) => console.error(message), 1504 }; 1505 1506 const nonExistentFilePath = './test/ut/initialization/nonExistentFile.json'; 1507 try { 1508 readNameCache(nonExistentFilePath, printObfHvigorLogger); 1509 } catch (err) { 1510 } 1511 const errorMessage = { 1512 code: '10804002', 1513 description: 'ArkTS compiler Error', 1514 cause: `Failed to open namecache file from ${nonExistentFilePath}, Error message: Test error`, 1515 position: nonExistentFilePath, 1516 solutions: [`Please check ${nonExistentFilePath} as error message suggested.`], 1517 }; 1518 expect(logger.error.calledWith(errorMessage)).to.be.false; 1519 }); 1520 }); 1521 1522 describe('handleUniversalPathInObf', () => { 1523 it('should handle universal paths correctly', () => { 1524 const mergedObConfig: MergedConfig = { 1525 options: new ObOptionsForTest(), 1526 reservedPropertyNames: [], 1527 reservedGlobalNames: [], 1528 reservedNames: [], 1529 reservedFileNames: [], 1530 keepComments: [], 1531 keepSourceOfPaths: [], 1532 universalReservedPropertyNames: [], 1533 universalReservedGlobalNames: [], 1534 keepUniversalPaths: [/test\.js$/], 1535 excludeUniversalPaths: [/exclude\.js$/], 1536 excludePathSet: new Set(), 1537 mergeKeepOptions: () => {}, 1538 mergeAllRules: () => {}, 1539 sortAndDeduplicate: () => {}, 1540 serializeMergedConfig: () => { 1541 return JSON.stringify(this); 1542 } 1543 }; 1544 const allSourceFilePaths = new Set([ 1545 'test.js', 1546 'exclude.js', 1547 'other.js', 1548 ]); 1549 1550 handleUniversalPathInObf(mergedObConfig, allSourceFilePaths); 1551 expect(mergedObConfig.keepSourceOfPaths).to.deep.equal(['test.js']); 1552 expect(mergedObConfig.excludePathSet).to.deep.equal(new Set(['exclude.js'])); 1553 }); 1554 1555 it('should return early if mergedObConfig is not provided or both keepUniversalPaths and excludeUniversalPaths are empty', () => { 1556 const mergedObConfig: MergedConfig = { 1557 options: new ObOptionsForTest(), 1558 reservedPropertyNames: [], 1559 reservedGlobalNames: [], 1560 reservedNames: [], 1561 reservedFileNames: [], 1562 keepComments: [], 1563 keepSourceOfPaths: [], 1564 universalReservedPropertyNames: [], 1565 universalReservedGlobalNames: [], 1566 keepUniversalPaths: [], 1567 excludeUniversalPaths: [], 1568 excludePathSet: new Set(), 1569 mergeKeepOptions: () => {}, 1570 mergeAllRules: () => {}, 1571 sortAndDeduplicate: () => {}, 1572 serializeMergedConfig: () => { 1573 return JSON.stringify(this); 1574 } 1575 }; 1576 const allSourceFilePaths = new Set([]); 1577 const result = handleUniversalPathInObf(mergedObConfig, allSourceFilePaths); 1578 1579 expect(result).to.be.undefined; 1580 }); 1581 }); 1582 1583 describe('getArkguardNameCache', () => { 1584 it('should return a JSON string with the correct structure', () => { 1585 const enablePropertyObfuscation = true; 1586 const enableFileNameObfuscation = true; 1587 const sdkVersion = '1.0.0'; 1588 const entryPackageInfo = 'packageInfo'; 1589 1590 const result = getArkguardNameCache(enablePropertyObfuscation, enableFileNameObfuscation, false, sdkVersion, entryPackageInfo); 1591 1592 try { 1593 JSON.parse(result); 1594 // If no error is thrown, the result is a valid JSON string 1595 console.log('Test passed: getArkguardNameCache returns a valid JSON string'); 1596 } catch (error) { 1597 console.error('Test failed: getArkguardNameCache does not return a valid JSON string'); 1598 } 1599 }); 1600 1601 it('should include the correct compileSdkVersion and entryPackageInfo', () => { 1602 const enablePropertyObfuscation = false; 1603 const enableFileNameObfuscation = false; 1604 const sdkVersion = '2.0.0'; 1605 const entryPackageInfo = 'anotherPackageInfo'; 1606 1607 const result = getArkguardNameCache(enablePropertyObfuscation, enableFileNameObfuscation, false, sdkVersion, entryPackageInfo); 1608 const parsedResult = JSON.parse(result); 1609 1610 expect(parsedResult.compileSdkVersion).to.equal(sdkVersion); 1611 expect(parsedResult.entryPackageInfo).to.equal(entryPackageInfo); 1612 }); 1613 1614 it('PropertyCache exists when enable export obfuscation', () => { 1615 const enablePropertyObfuscation = false; 1616 const enableFileNameObfuscation = false; 1617 const enableExportObfuscation = true; 1618 const sdkVersion = '2.0.0'; 1619 const entryPackageInfo = 'anotherPackageInfo'; 1620 1621 PropCollections.historyMangledTable.set("key1", "value1"); 1622 PropCollections.historyMangledTable.set("key2", "value2"); 1623 PropCollections.globalMangledTable.set("key3", "value3"); 1624 PropCollections.globalMangledTable.set("key4", "value4"); 1625 const result = getArkguardNameCache(enablePropertyObfuscation, enableFileNameObfuscation, enableExportObfuscation, sdkVersion, entryPackageInfo); 1626 const parsedResult = JSON.parse(result); 1627 PropCollections.historyMangledTable.clear(); 1628 PropCollections.globalMangledTable.clear(); 1629 expect('PropertyCache' in parsedResult).to.be.true; 1630 expect(parsedResult.PropertyCache.key1 === "value1").to.be.true; 1631 expect(parsedResult.PropertyCache.key2 === "value2").to.be.true; 1632 expect(parsedResult.PropertyCache.key3 === "value3").to.be.true; 1633 expect(parsedResult.PropertyCache.key4 === "value4").to.be.true; 1634 }); 1635 }); 1636 1637 describe('fillNameCache', function() { 1638 it('should correctly fill the name cache with the given table entries', function() { 1639 const table = new Map([ 1640 ['key1', 'value1'], 1641 ['key2', 'value2'], 1642 ['key3', 'value3'] 1643 ]); 1644 const nameCache = new Map(); 1645 1646 fillNameCache(table, nameCache); 1647 1648 assert.deepEqual(nameCache, table); 1649 }); 1650 1651 it('should handle empty tables gracefully', function() { 1652 const table = new Map(); 1653 const nameCache = new Map(); 1654 1655 fillNameCache(table, nameCache); 1656 1657 assert.deepEqual(nameCache, table); 1658 }); 1659 }); 1660 1661 describe('writeObfuscationNameCache', () => { 1662 let existsSyncSpy; 1663 let mkdirSyncSpy; 1664 let writeFileSyncSpy; 1665 1666 beforeEach(function() { 1667 existsSyncSpy = sinon.spy(fs, 'existsSync'); 1668 mkdirSyncSpy = sinon.spy(fs, 'mkdirSync'); 1669 writeFileSyncSpy = sinon.spy(fs, 'writeFileSync'); 1670 }); 1671 1672 afterEach(function() { 1673 existsSyncSpy.restore(); 1674 mkdirSyncSpy.restore(); 1675 writeFileSyncSpy.restore(); 1676 }); 1677 1678 it('should not write cache if projectConfig.arkObfuscator is false', () => { 1679 const projectConfig = { 1680 arkObfuscator: false, 1681 obfuscationMergedObConfig: { 1682 options: { 1683 enablePropertyObfuscation: true, 1684 enableFileNameObfuscation: true, 1685 }, 1686 }, 1687 etsLoaderVersion: '1.0.0', 1688 }; 1689 const entryPackageInfo = 'testEntryPackageInfo'; 1690 const obfuscationCacheDir = 'testCacheDir'; 1691 const printNameCache = 'testPrintNameCache'; 1692 1693 writeObfuscationNameCache(projectConfig, entryPackageInfo, obfuscationCacheDir, printNameCache); 1694 1695 expect(existsSyncSpy.called).to.be.false; 1696 expect(mkdirSyncSpy.called).to.be.false; 1697 expect(writeFileSyncSpy.called).to.be.false; 1698 }); 1699 it('should write cache to obfuscationCacheDir if provided', () => { 1700 const projectConfig = { 1701 arkObfuscator: true, 1702 obfuscationMergedObConfig: { 1703 options: { 1704 enablePropertyObfuscation: true, 1705 enableFileNameObfuscation: true, 1706 enableExportObfusaction: true 1707 }, 1708 }, 1709 etsLoaderVersion: '1.0.0', 1710 }; 1711 const entryPackageInfo = 'testEntryPackageInfo'; 1712 const obfuscationCacheDir = './test/ut/initialization/testObfuscationCacheDir'; 1713 const printNameCache = ''; 1714 writeObfuscationNameCache(projectConfig, entryPackageInfo, obfuscationCacheDir, printNameCache); 1715 const defaultNameCachePath: string = path.join(obfuscationCacheDir, 'nameCache.json'); 1716 const expectedContent = { 1717 "extraKey": "", 1718 "compileSdkVersion": "1.0.0", 1719 "entryPackageInfo": "testEntryPackageInfo", 1720 "PropertyCache": {}, 1721 "FileNameCache": {} 1722 } 1723 const jsonData = fs.readFileSync(defaultNameCachePath,'utf-8'); 1724 const result = JSON.parse(jsonData); 1725 expect(result).to.deep.equal(expectedContent); 1726 fs.unlinkSync(defaultNameCachePath); 1727 fs.rmdirSync(path.dirname(defaultNameCachePath)); 1728 }); 1729 it('should write cache to printNameCache if provided', () => { 1730 const projectConfig = { 1731 arkObfuscator: true, 1732 obfuscationMergedObConfig: { 1733 options: { 1734 enablePropertyObfuscation: true, 1735 enableFileNameObfuscation: true, 1736 }, 1737 }, 1738 etsLoaderVersion: '1.0.0', 1739 }; 1740 const entryPackageInfo = 'testEntryPackageInfo'; 1741 const obfuscationCacheDir = ''; 1742 const printNameCache = './test/ut/initialization/printNameCache.json'; 1743 writeObfuscationNameCache(projectConfig, entryPackageInfo, obfuscationCacheDir, printNameCache); 1744 const expectedContent = { 1745 "extraKey": "", 1746 "compileSdkVersion": "1.0.0", 1747 "entryPackageInfo": "testEntryPackageInfo", 1748 "PropertyCache": {}, 1749 "FileNameCache": {} 1750 } 1751 const jsonData = fs.readFileSync(printNameCache,'utf-8'); 1752 const result = JSON.parse(jsonData); 1753 expect(result).to.deep.equal(expectedContent); 1754 expect(existsSyncSpy.called).to.be.false; 1755 expect(mkdirSyncSpy.called).to.be.false; 1756 fs.unlinkSync(printNameCache); 1757 }); 1758 }); 1759 1760 describe('enableObfuscatedFilePathConfig', () => { 1761 it('should return false if in debug mode or no obfuscation config', () => { 1762 const projectConfig = { 1763 obfuscationMergedObConfig: null, 1764 buildMode: 'debug' 1765 }; 1766 const result = enableObfuscatedFilePathConfig(true, projectConfig); 1767 expect(result).to.be.false; 1768 }); 1769 1770 it('should return false if obfuscation is disabled or file name obfuscation is not enabled', () => { 1771 const projectConfig = { 1772 obfuscationMergedObConfig: { 1773 options: { 1774 disableObfuscation: true, 1775 enableFileNameObfuscation: false, 1776 }, 1777 }, 1778 buildMode: 'debug' 1779 }; 1780 const result = enableObfuscatedFilePathConfig(false, projectConfig); 1781 expect(result).to.be.false; 1782 }); 1783 1784 it('should return true if all conditions are met', () => { 1785 const projectConfig = { 1786 obfuscationMergedObConfig: { 1787 options: { 1788 disableObfuscation: false, 1789 enableFileNameObfuscation: true, 1790 }, 1791 }, 1792 buildMode: 'not debug' 1793 }; 1794 const result = enableObfuscatedFilePathConfig(false, projectConfig); 1795 expect(result).to.be.true; 1796 }); 1797 }); 1798 1799 describe('handleObfuscatedFilePath', () => { 1800 it('should return the original file path if obfuscation is not enabled', () => { 1801 const filePath = '/path/to/file.js'; 1802 const isPackageModules = false; 1803 const projectConfig = { 1804 enableFileNameObfuscation: false, 1805 buildMode: 'debug' 1806 }; 1807 1808 const result = handleObfuscatedFilePath(filePath, isPackageModules, projectConfig); 1809 1810 expect(result).to.equal(filePath); 1811 }); 1812 1813 it('should return the original file path if obfuscation is not enabled', () => { 1814 const filePath = '/path/to/file.txt'; 1815 const isPackageModules = false; 1816 const projectConfig = { 1817 obfuscationMergedObConfig: null, 1818 buildMode: 'debug' 1819 }; 1820 const result = handleObfuscatedFilePath(filePath, isPackageModules, projectConfig); 1821 expect(result).to.equal(filePath); 1822 }); 1823 1824 it('should return the original file path if obfuscation is not enabled', () => { 1825 const filePath = '/path/to/file.txt'; 1826 const isPackageModules = false; 1827 const projectConfig = { 1828 obfuscationMergedObConfig: null, 1829 buildMode: 'not debug' 1830 }; 1831 const result = handleObfuscatedFilePath(filePath, isPackageModules, projectConfig); 1832 expect(result).to.equal(filePath); 1833 }); 1834 1835 it('should return the unix formatted file path if obfuscation is enabled and is a package module', () => { 1836 const filePath = '/path/to/file.js'; 1837 const isPackageModules = true; 1838 const projectConfig = { 1839 obfuscationMergedObConfig: { 1840 options: { 1841 disableObfuscation: false, 1842 enableFileNameObfuscation: true, 1843 }, 1844 }, 1845 buildMode: "not Debug" 1846 }; 1847 1848 const result = handleObfuscatedFilePath(filePath, isPackageModules, projectConfig); 1849 1850 expect(result).to.equal(FileUtils.toUnixPath(filePath)); 1851 }); 1852 1853 it('should return the unix formatted file path if obfuscation is enabled and is a package module', () => { 1854 const filePath = '/path/to/file.js'; 1855 const isPackageModules = true; 1856 const projectConfig = { 1857 obfuscationMergedObConfig: { 1858 options: { 1859 disableObfuscation: false, 1860 enableFileNameObfuscation: true, 1861 }, 1862 }, 1863 buildMode: "" 1864 }; 1865 1866 const result = handleObfuscatedFilePath(filePath, isPackageModules, projectConfig); 1867 1868 expect(result).to.equal(FileUtils.toUnixPath(filePath)); 1869 }); 1870 }); 1871 1872 describe('enableObfuscateFileName', () => { 1873 it('should return false if obfuscation is not enabled', () => { 1874 const isPackageModules = false; 1875 const projectConfig = { 1876 obfuscationMergedObConfig: null, 1877 buildMode: "not Debug" 1878 }; 1879 const result = enableObfuscateFileName(isPackageModules, projectConfig); 1880 expect(result).to.be.false; 1881 }); 1882 1883 it('should return true if obfuscation is enabled and not a package module', () => { 1884 const isPackageModules = false; 1885 const projectConfig = { 1886 obfuscationMergedObConfig: { 1887 options: { 1888 disableObfuscation: false, 1889 enableFileNameObfuscation: true, 1890 }, 1891 }, 1892 buildMode: "not Debug" 1893 }; 1894 const result = enableObfuscateFileName(isPackageModules, projectConfig); 1895 1896 expect(result).to.be.true; 1897 }); 1898 1899 it('should return false if obfuscation is enabled and is a package module', () => { 1900 const isPackageModules = true; 1901 const projectConfig = { 1902 obfuscationMergedObConfig: { 1903 options: { 1904 disableObfuscation: false, 1905 enableFileNameObfuscation: true, 1906 }, 1907 }, 1908 buildMode: "Debug" 1909 }; 1910 const result = enableObfuscateFileName(isPackageModules, projectConfig); 1911 expect(result).to.be.false; 1912 }); 1913 1914 it('should return false if obfuscation is enabled and is a package module', () => { 1915 const isPackageModules = true; 1916 const projectConfig = { 1917 obfuscationMergedObConfig: { 1918 options: { 1919 disableObfuscation: false, 1920 enableFileNameObfuscation: false, 1921 }, 1922 }, 1923 buildMode: "Debug" 1924 }; 1925 const result = enableObfuscateFileName(isPackageModules, projectConfig); 1926 expect(result).to.be.false; 1927 }); 1928 1929 it('should return false if obfuscation is enabled and is a package module', () => { 1930 const isPackageModules = true; 1931 const projectConfig = { 1932 obfuscationMergedObConfig: {}, 1933 buildMode: "Debug" 1934 }; 1935 const result = enableObfuscateFileName(isPackageModules, projectConfig); 1936 expect(result).to.be.false; 1937 }); 1938 1939 it('should return false if obfuscation is enabled and is a package module', () => { 1940 const isPackageModules = true; 1941 const projectConfig = { 1942 obfuscationMergedObConfig: null, 1943 buildMode: "Debug" 1944 }; 1945 const result = enableObfuscateFileName(isPackageModules, projectConfig); 1946 expect(result).to.be.false; 1947 }); 1948 1949 it('should return false if obfuscation is enabled and is a package module', () => { 1950 const isPackageModules = true; 1951 const projectConfig = { 1952 obfuscationMergedObConfig: undefined, 1953 buildMode: "Debug" 1954 }; 1955 const result = enableObfuscateFileName(isPackageModules, projectConfig); 1956 expect(result).to.be.false; 1957 }); 1958 1959 it('should return false if obfuscation is enabled and is a package module', () => { 1960 const isPackageModules = true; 1961 const projectConfig = { 1962 obfuscationMergedObConfig: { 1963 options: { 1964 disableObfuscation: false, 1965 enableFileNameObfuscation: true, 1966 }, 1967 }, 1968 buildMode: "not Debug" 1969 }; 1970 const result = enableObfuscateFileName(isPackageModules, projectConfig); 1971 expect(result).to.be.false; 1972 }); 1973 1974 it('should return false if obfuscation is enabled and is a package module', () => { 1975 const isPackageModules = true; 1976 const projectConfig = { 1977 obfuscationMergedObConfig: { 1978 options: { 1979 disableObfuscation: false, 1980 enableFileNameObfuscation: false, 1981 }, 1982 }, 1983 buildMode: "not Debug" 1984 }; 1985 const result = enableObfuscateFileName(isPackageModules, projectConfig); 1986 expect(result).to.be.false; 1987 }); 1988 1989 it('should return false if obfuscation is enabled and is a package module', () => { 1990 const isPackageModules = true; 1991 const projectConfig = { 1992 obfuscationMergedObConfig: { 1993 options: { 1994 disableObfuscation: false, 1995 enableFileNameObfuscation: false, 1996 }, 1997 }, 1998 buildMode: "not Debug" 1999 }; 2000 const result = enableObfuscateFileName(isPackageModules, projectConfig); 2001 expect(result).to.be.false; 2002 }); 2003 2004 it('should return false if obfuscation is enabled and is a package module', () => { 2005 const isPackageModules = true; 2006 const projectConfig = { 2007 obfuscationMergedObConfig: { 2008 options: { 2009 disableObfuscation: false, 2010 enableFileNameObfuscation: true, 2011 }, 2012 }, 2013 buildMode: "not Debug" 2014 }; 2015 const result = enableObfuscateFileName(isPackageModules, projectConfig); 2016 expect(result).to.be.false; 2017 }); 2018 }); 2019 2020 describe('getRelativeSourcePath', () => { 2021 it('should return the relative path of a file within the project root', () => { 2022 const filePath = '/Users/user/project/src/components/Button.js'; 2023 const projectRootPath = '/Users/user/project'; 2024 const expectedRelativePath = 'src/components/Button.js'; 2025 2026 const result = getRelativeSourcePath(filePath, projectRootPath, ''); 2027 expect(result).to.equal(expectedRelativePath); 2028 }); 2029 2030 it('should return the relative path of a file within a specified project path', () => { 2031 const filePath = '/Users/user/project/src/components/Button.js'; 2032 const belongProjectPath = '/Users/user/project/src'; 2033 const expectedRelativePath = 'components/Button.js'; 2034 2035 const result = getRelativeSourcePath(filePath, '', belongProjectPath); 2036 expect(result).to.equal(expectedRelativePath); 2037 }); 2038 2039 it('should return the original path if no project root or belong project path is provided', () => { 2040 const filePath = '/Users/user/project/src/components/Button.js'; 2041 const expectedRelativePath = filePath; 2042 2043 const result = getRelativeSourcePath(filePath, '', ''); 2044 expect(result).to.equal(expectedRelativePath); 2045 }); 2046 }); 2047 2048 describe('printUnobfuscationReasons', () => { 2049 it('historyAllUnobfuscatedNamesMap is empty', () => { 2050 unobfuscationNamesObj['Index.ets'] = { 'abc': ['sdk'] }; 2051 unobfuscationNamesObj['Test.ets'] = { 'abc_test': ['conf'] }; 2052 printUnobfuscationReasons('', './keptNames.json'); 2053 let keptNamesObj = { 2054 keptReasons: {}, 2055 keptNames: {} 2056 }; 2057 let keptNameString = fs.readFileSync('./keptNames.json', 'utf-8'); 2058 const parsedObj = JSON.parse(keptNameString); 2059 keptNamesObj.keptReasons = parsedObj.keptReasons; 2060 keptNamesObj.keptNames = parsedObj.keptNames; 2061 expect(keptNamesObj.keptNames['Index.ets']['abc'][0]).to.equal('sdk'); 2062 expect(keptNamesObj.keptNames['Test.ets']['abc_test'][0]).to.equal('conf'); 2063 clearHistoryUnobfuscatedMap(); 2064 clearUnobfuscationNamesObj(); 2065 }); 2066 2067 it('historyAllUnobfuscatedNamesMap is not empty', () => { 2068 historyAllUnobfuscatedNamesMap.set('Index.ets', { 'abc': ['sdk'] }); 2069 historyAllUnobfuscatedNamesMap.set('Test.ets', { 'abc_test': ['conf'] }); 2070 unobfuscationNamesObj['Index.ets'] = { 'abc': ['conf'] }; 2071 unobfuscationNamesObj['Test2.ets'] = { 'abc_test2': ['lang'] }; 2072 printUnobfuscationReasons('', './keptNames.json'); 2073 let keptNamesObj = { 2074 keptReasons: {}, 2075 keptNames: {} 2076 }; 2077 let keptNameString = fs.readFileSync('./keptNames.json', 'utf-8'); 2078 const parsedObj = JSON.parse(keptNameString); 2079 keptNamesObj.keptReasons = parsedObj.keptReasons; 2080 keptNamesObj.keptNames = parsedObj.keptNames; 2081 expect(keptNamesObj.keptNames['Index.ets']['abc'][0]).to.equal('conf'); 2082 expect(keptNamesObj.keptNames['Test.ets']['abc_test'][0]).to.equal('conf'); 2083 expect(keptNamesObj.keptNames['Test2.ets']['abc_test2'][0]).to.equal('lang'); 2084 clearHistoryUnobfuscatedMap(); 2085 clearUnobfuscationNamesObj(); 2086 }); 2087 }); 2088 2089 describe('clearNameCache', () => { 2090 it('should clear historyMangledTable and nameCacheMap', () => { 2091 PropCollections.historyMangledTable.set('name1','name2'); 2092 nameCacheMap.set('name1','name2'); 2093 historyAllUnobfuscatedNamesMap.set('key', {'prop1': 'aaa'}); 2094 historyUnobfuscatedPropMap.set('key', ['value']); 2095 clearNameCache(); 2096 expect(PropCollections.historyMangledTable.size).to.be.equal(0); 2097 expect(nameCacheMap.size).to.be.equal(0); 2098 expect(historyAllUnobfuscatedNamesMap.size).to.equal(0); 2099 expect(historyUnobfuscatedPropMap.size).to.equal(0); 2100 }); 2101 }); 2102 2103 describe('emitConsumerConfigFiles', () => { 2104 it('should also collect atKeepNames when atKeep is enabled', () => { 2105 const atKeepExportedPath = path.join(__dirname, '../../testData/output/atKeep_obfuscation01.txt'); 2106 const sourceObConfig = { 2107 selfConfig: { 2108 ruleOptions: { 2109 enable: true, 2110 rules: ['./test/testData/obfuscation/testAtKeep/obfuscation-rules-atKeep.txt'] 2111 }, 2112 consumerRules: ['./test/testData/obfuscation/testAtKeep/consumer-rules.txt'], 2113 }, 2114 dependencies: { libraries: [], hars: [] }, 2115 obfuscationCacheDir: './test/testData/cache', 2116 options: { 2117 disableObfuscation: false 2118 }, 2119 exportRulePath: atKeepExportedPath, 2120 sdkApis: [] 2121 }; 2122 const projectConfig = { 2123 obfuscationOptions: sourceObConfig, 2124 compileHar: false, 2125 compileShared: true 2126 } 2127 const obConfigResolver = new ObConfigResolver(projectConfig, printObfLogger); 2128 obConfigResolver.resolveObfuscationConfigs(); 2129 AtKeepCollections.clear(); 2130 AtKeepCollections.keepAsConsumer.globalNames.add('globalName1'); 2131 AtKeepCollections.keepAsConsumer.propertyNames.add('propertyName1'); 2132 AtKeepCollections.keepSymbol.globalNames.add('globalName2'); 2133 AtKeepCollections.keepSymbol.propertyNames.add('propertyName2'); 2134 obConfigResolver.emitConsumerConfigFiles(); 2135 const atKeepContent = fs.readFileSync(sourceObConfig.exportRulePath, 'utf-8'); 2136 expect(atKeepContent).to.include('-enable-property-obfuscation'); 2137 expect(atKeepContent).to.include('-keep-global-name'); 2138 expect(atKeepContent).to.include('globalName00'); 2139 expect(atKeepContent).to.include('globalName1'); 2140 expect(atKeepContent).to.include('-keep-property-name'); 2141 expect(atKeepContent).to.include('propertyName00'); 2142 expect(atKeepContent).to.include('propertyName1'); 2143 expect(atKeepContent).not.to.include('globalName2'); 2144 expect(atKeepContent).not.to.include('propertyName2'); 2145 FileUtils.deleteFile(atKeepExportedPath); 2146 }); 2147 2148 it('should not collect atKeepNames when atKeep is not enabled', () => { 2149 const atKeepExportedPath = path.join(__dirname, '../../testData/output/atKeep_obfuscation02.txt'); 2150 const sourceObConfig = { 2151 selfConfig: { 2152 ruleOptions: { 2153 enable: true, 2154 rules: ['./test/testData/obfuscation/testAtKeep/obfuscation-rules.txt'] 2155 }, 2156 consumerRules: ['./test/testData/obfuscation/testAtKeep/consumer-rules.txt'], 2157 }, 2158 dependencies: { libraries: [], hars: [] }, 2159 obfuscationCacheDir: './test/testData/cache', 2160 options: { 2161 disableObfuscation: false 2162 }, 2163 exportRulePath: atKeepExportedPath, 2164 sdkApis: [] 2165 }; 2166 const projectConfig = { 2167 obfuscationOptions: sourceObConfig, 2168 compileHar: false, 2169 compileShared: true 2170 } 2171 AtKeepCollections.clear(); 2172 const obConfigResolver = new ObConfigResolver(projectConfig, printObfLogger); 2173 obConfigResolver.resolveObfuscationConfigs(); 2174 const atKeepContent = fs.readFileSync(sourceObConfig.exportRulePath, 'utf-8'); 2175 expect(atKeepContent).to.include('-enable-property-obfuscation'); 2176 expect(atKeepContent).to.include('-keep-global-name'); 2177 expect(atKeepContent).to.include('globalName00'); 2178 expect(atKeepContent).not.to.include('globalName1'); 2179 expect(atKeepContent).to.include('-keep-property-name'); 2180 expect(atKeepContent).to.include('propertyName00'); 2181 expect(atKeepContent).not.to.include('propertyName1'); 2182 expect(atKeepContent).not.to.include('globalName2'); 2183 expect(atKeepContent).not.to.include('propertyName2'); 2184 FileUtils.deleteFile(atKeepExportedPath); 2185 }); 2186 }); 2187}); 2188