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} from '../../../src/initialization/ConfigResolver'; 36import { PropCollections, renameFileNameModule } from '../../../src/ArkObfuscator'; 37import { nameCacheMap } from '../../../src/initialization/CommonObject'; 38import path from 'path'; 39import fs from 'fs'; 40import { FileUtils } from '../../../src/utils/FileUtils'; 41import sinon from 'sinon'; 42import { UnobfuscationCollections } from '../../../src/utils/CommonCollections'; 43 44const OBFUSCATE_TESTDATA_DIR = path.resolve(__dirname, '../../testData/obfuscation/system_api_obfuscation'); 45const projectConfig = { 46 obfuscationOptions: { option1: 'value1' }, 47 compileHar: true 48}; 49const logger = console; 50const isTerser = false; 51let newObConfigResolver = new ObConfigResolver(projectConfig, logger, isTerser); 52 53describe('test for ConfigResolve', function() { 54 describe('ObOptions', () => { 55 it('should merge options correctly', () => { 56 const ob1 = new ObOptionsForTest(); 57 ob1.disableObfuscation = true; 58 ob1.enablePropertyObfuscation = true; 59 60 const ob2 = new ObOptionsForTest(); 61 ob2.enableToplevelObfuscation = true; 62 ob2.printNameCache = 'test'; 63 ob2.printKeptNamesPath = './test/ut/initialization/printKeptNamesPath.txt'; 64 ob2.applyNameCache = 'test case'; 65 66 ob1.merge(ob2); 67 68 expect(ob1.disableObfuscation).to.be.true; 69 expect(ob1.enablePropertyObfuscation).to.be.true; 70 expect(ob1.enableToplevelObfuscation).to.be.true; 71 expect(ob1.printNameCache).to.equal('test'); 72 expect(ob1.printKeptNamesPath).to.equal('./test/ut/initialization/printKeptNamesPath.txt'); 73 expect(ob1.applyNameCache).to.equal('test case'); 74 }); 75 }); 76 77 describe('MergedConfig', () => { 78 it('should merge two MergedConfig instances correctly', () => { 79 const config1 = new MergedConfig(); 80 config1.reservedPropertyNames = ['prop1']; 81 config1.reservedGlobalNames = ['global1']; 82 config1.keepComments = ['comment1']; 83 config1.excludePathSet.add('path1'); 84 85 const config2 = new MergedConfig(); 86 config2.reservedPropertyNames = ['prop2']; 87 config2.reservedGlobalNames = ['global2']; 88 config2.keepComments = ['comment2']; 89 config2.excludePathSet.add('path2'); 90 91 config1.merge(config2); 92 93 expect(config1.reservedPropertyNames).to.deep.equal(['prop1', 'prop2']); 94 expect(config1.reservedGlobalNames).to.deep.equal(['global1', 'global2']); 95 expect(config1.keepComments).to.deep.equal(['comment1', 'comment2']); 96 expect(config1.excludePathSet).to.deep.equal(new Set(['path1', 'path2'])); 97 }); 98 99 it('should sort and deduplicate arrays correctly', () => { 100 const config = new MergedConfig(); 101 config.reservedPropertyNames = ['prop2', 'prop1', 'prop1']; 102 config.reservedGlobalNames = ['global2', 'global1', 'global1']; 103 config.keepComments = ['comment2', 'comment1', 'comment1']; 104 105 config.sortAndDeduplicate(); 106 107 expect(config.reservedPropertyNames).to.deep.equal(['prop1', 'prop2']); 108 expect(config.reservedGlobalNames).to.deep.equal(['global1', 'global2']); 109 expect(config.keepComments).to.deep.equal(['comment1', 'comment2']); 110 }); 111 112 it('should serialize merged config correctly', () => { 113 let resultStr: string = ''; 114 const config = new MergedConfig(); 115 config.options = new ObOptionsForTest(); 116 config.options['option1'] = true; 117 config.options['option2'] = false; 118 config.options['disableObfuscation'] = true; 119 config.options['enableStringPropertyObfuscation'] = true; 120 config.reservedGlobalNames = ['global1']; 121 config.reservedPropertyNames = ['prop1']; 122 123 const serialized = config.serializeMergedConfig(); 124 const serializedExportSwitchMap = new Map([ 125 ['disableObfuscation', ObConfigResolver.KEEP_DTS], 126 ['enablePropertyObfuscation', ObConfigResolver.ENABLE_PROPERTY_OBFUSCATION], 127 ['enableStringPropertyObfuscation', ObConfigResolver.ENABLE_STRING_PROPERTY_OBFUSCATION], 128 ['enableToplevelObfuscation', ObConfigResolver.ENABLE_TOPLEVEL_OBFUSCATION], 129 ['compact', ObConfigResolver.COMPACT], 130 ['removeLog', ObConfigResolver.REMOVE_LOG], 131 ]); 132 133 expect(serialized).to.include(ObConfigResolver.KEEP_GLOBAL_NAME); 134 expect(serialized).to.include('global1'); 135 expect(serialized).to.include(ObConfigResolver.KEEP_PROPERTY_NAME); 136 expect(serialized).to.include('prop1'); 137 expect(serialized).to.not.include('option2'); 138 139 expect(ObConfigResolver.exportedSwitchMap.has(String('disableObfuscation'))).to.be.true; 140 expect(ObConfigResolver.exportedSwitchMap.has(String('enableStringPropertyObfuscation'))).to.be.true; 141 expect(resultStr).to.equal(''); 142 }); 143 }); 144 145 describe('ObConfigResolver', () => { 146 describe('constructor', () => { 147 it('should create an instance with the correct properties', () => { 148 const projectConfig = { 149 obfuscationOptions: { option1: 'value1' }, 150 compileHar: true 151 }; 152 const logger = console; 153 const isTerser = false; 154 const myInstance = new ObConfigResolver(projectConfig, logger, isTerser); 155 156 expect(myInstance).to.be.an('object'); 157 expect(myInstance.sourceObConfig).to.deep.equal({ option1: 'value1' }); 158 expect(myInstance.logger).to.equal(console); 159 expect(myInstance.isHarCompiled).to.be.true; 160 expect(myInstance.isTerser).to.be.false; 161 }); 162 163 it('should create an instance with Terser enabled', () => { 164 const projectConfig = { 165 obfuscationOptions: { option1: 'value1' }, 166 compileHar: true 167 }; 168 const logger = console; 169 const myInstance = new ObConfigResolver(projectConfig, logger, true); 170 171 expect(myInstance).to.be.an('object'); 172 expect(myInstance.sourceObConfig).to.deep.equal({ option1: 'value1' }); 173 expect(myInstance.logger).to.equal(console); 174 expect(myInstance.isHarCompiled).to.be.true; 175 expect(myInstance.isTerser).to.be.true; 176 }); 177 }); 178 179 describe('resolveObfuscationConfigs', () => { 180 const projectConfig = { 181 obfuscationOptions: { option1: 'value1' }, 182 compileHar: true 183 }; 184 const logger = console; 185 const isTerser = false; 186 let newObConfigResolver = new ObConfigResolver(projectConfig, logger, isTerser); 187 let testClass: ObConfigResolver & { 188 performancePrinter?: any; 189 }; 190 testClass = newObConfigResolver; 191 192 it('should return a MergedConfig object when sourceObConfig is undefined', () => { 193 testClass.sourceObConfig = undefined; 194 testClass.isHarCompiled = true; 195 testClass.performancePrinter = {}; 196 const result = testClass.resolveObfuscationConfigs(); 197 generateConsumerObConfigFile(testClass.sourceObConfig, undefined); 198 199 expect(testClass.sourceObConfig).to.be.an.undefined; 200 expect(result).to.deep.equal(new MergedConfig()); 201 expect(result).to.be.an('object'); 202 expect(result).to.have.property('options'); 203 }); 204 205 it('should return a MergedConfig object when sourceObConfig is null', () => { 206 testClass.sourceObConfig = null; 207 testClass.isHarCompiled = true; 208 testClass.performancePrinter = {}; 209 const result = testClass.resolveObfuscationConfigs(); 210 generateConsumerObConfigFile(null, undefined); 211 212 expect(testClass.sourceObConfig).to.be.a.null; 213 expect(result).to.deep.equal(new MergedConfig()); 214 expect(result).to.be.an('object'); 215 expect(result).to.have.property('options'); 216 }); 217 218 it('should handle the case when sourceObConfig.selfConfig.ruleOptions.enable is false', function () { 219 testClass.sourceObConfig = { 220 selfConfig: { 221 ruleOptions: { enable: false }, 222 }, 223 dependencies: { libraries: [], hars: [] }, 224 }; 225 generateConsumerObConfigFile(testClass.sourceObConfig, undefined); 226 const result = testClass.resolveObfuscationConfigs(); 227 228 expect(result).to.be.an('object'); 229 expect(result).to.have.property('options'); 230 expect(result.options.disableObfuscation).to.be.true; 231 }); 232 233 it('should handle the case when sourceObConfig.selfConfig.ruleOptions.enable is true', function () { 234 testClass.sourceObConfig = { 235 selfConfig: { 236 ruleOptions: { enable: true }, 237 }, 238 dependencies: { libraries: [], hars: [] }, 239 }; 240 generateConsumerObConfigFile(testClass.sourceObConfig, undefined); 241 const result = testClass.resolveObfuscationConfigs(); 242 243 expect(result).to.be.an('object'); 244 expect(result).to.have.property('options'); 245 expect(result.options.disableObfuscation).to.be.false; 246 }); 247 248 it('should handle the case when enableObfuscation is false', () => { 249 const sourceObConfig = { 250 selfConfig: { 251 ruleOptions: { enable: false }, 252 consumerRules: ['./test/testData/obfuscation/keepDts/obfuscation-template.txt'], 253 }, 254 dependencies: { libraries: [], hars: [] }, 255 obfuscationCacheDir: './test/testData/cache', 256 options: { 257 disableObfuscation: true 258 } 259 }; 260 const isHarCompiled = true; 261 let enableObfuscation = sourceObConfig.selfConfig.ruleOptions.enable; 262 let selfConfig = new MergedConfig(); 263 enableObfuscation = !selfConfig.options.disableObfuscation; 264 let needConsumerConfigs = isHarCompiled && sourceObConfig.selfConfig.consumerRules && 265 sourceObConfig.selfConfig.consumerRules.length > 0; 266 let needDependencyConfigs = enableObfuscation || needConsumerConfigs; 267 let dependencyConfigs = new MergedConfig(); 268 const dependencyMaxLength = Math.max( 269 sourceObConfig.dependencies.libraries.length, 270 sourceObConfig.dependencies.hars.length, 271 ); 272 newObConfigResolver.getDependencyConfigsForTest(sourceObConfig, dependencyConfigs); 273 274 expect(needConsumerConfigs).to.be.true; 275 expect(!dependencyMaxLength).to.be.true; 276 expect(needDependencyConfigs).to.be.true; 277 expect(dependencyConfigs).to.deep.equal(new MergedConfig()); 278 expect(enableObfuscation).to.be.true; 279 }); 280 281 it('should handle the case when enableObfuscation is false', () => { 282 const sourceObConfig = { 283 selfConfig: { 284 options: { 285 disableObfuscation: false, 286 enablePropertyObfuscation: true, 287 enableExportObfuscation: true, 288 enableToplevelObfuscation:true 289 }, 290 ruleOptions: { enable: true }, 291 consumerRules: ['./test/testData/obfuscation/keepDts/obfuscation-template.txt'], 292 }, 293 dependencies: { libraries: [1, 2, 3], hars: [] }, 294 obfuscationCacheDir: './test/testData/cache', 295 }; 296 const isHarCompiled = true; 297 let enableObfuscation = sourceObConfig.selfConfig.ruleOptions.enable; 298 let selfConfig = new MergedConfig(); 299 enableObfuscation = !selfConfig.options.disableObfuscation; 300 let needConsumerConfigs = isHarCompiled && sourceObConfig.selfConfig.consumerRules && 301 sourceObConfig.selfConfig.consumerRules.length > 0; 302 let needDependencyConfigs = enableObfuscation || needConsumerConfigs; 303 let dependencyConfigs = new MergedConfig(); 304 const dependencyMaxLength = Math.max( 305 sourceObConfig.dependencies.libraries.length, 306 sourceObConfig.dependencies.hars.length, 307 ); 308 const mergedConfigs = newObConfigResolver.getMergedConfigsForTest(selfConfig, dependencyConfigs); 309 newObConfigResolver.handleReservedArrayForTest(mergedConfigs); 310 let needKeepSystemApi = enableObfuscation && 311 (mergedConfigs.options.enablePropertyObfuscation || 312 (mergedConfigs.options.enableExportObfuscation && mergedConfigs.options.enableToplevelObfuscation)); 313 314 newObConfigResolver.getDependencyConfigsForTest(sourceObConfig, dependencyConfigs); 315 316 expect(needConsumerConfigs).to.be.true; 317 expect(!dependencyMaxLength).to.be.false; 318 expect(needDependencyConfigs).to.be.true; 319 expect(dependencyConfigs).to.deep.equal(new MergedConfig()); 320 expect(enableObfuscation).to.be.true; 321 expect(needKeepSystemApi).to.be.false; 322 expect(needConsumerConfigs).to.be.true; 323 }); 324 325 it('should handle the case when enableObfuscation is true', () => { 326 testClass.sourceObConfig = { 327 selfConfig: { 328 ruleOptions: { enable: true }, 329 consumerRules: ['./test/testData/obfuscation/keepDts/obfuscation-template.txt'], 330 }, 331 dependencies: { libraries: [], hars: [] }, 332 obfuscationCacheDir: './test/testData/cache', 333 options: { 334 disableObfuscation: true 335 } 336 }; 337 testClass.isHarCompiled = true; 338 testClass.performancePrinter = {}; 339 let enableObfuscation = testClass.sourceObConfig.selfConfig.ruleOptions.enable; 340 let selfConfig = new MergedConfig(); 341 newObConfigResolver.getSelfConfigsForTest(selfConfig); 342 enableObfuscation = !selfConfig.options.disableObfuscation; 343 enableObfuscation = false; 344 let needConsumerConfigs = testClass.isHarCompiled && testClass.sourceObConfig.selfConfig.consumerRules && 345 testClass.sourceObConfig.selfConfig.consumerRules.length > 0; 346 let needDependencyConfigs = enableObfuscation || needConsumerConfigs; 347 let dependencyConfigs = new MergedConfig(); 348 const dependencyMaxLength = Math.max( 349 testClass.sourceObConfig.dependencies.libraries.length, 350 testClass.sourceObConfig.dependencies.hars.length, 351 ); 352 newObConfigResolver.getDependencyConfigsForTest(testClass.sourceObConfig, dependencyConfigs); 353 354 expect(needConsumerConfigs).to.be.true; 355 expect(!dependencyMaxLength).to.be.true; 356 expect(needDependencyConfigs).to.be.true; 357 expect(dependencyConfigs).to.deep.equal(new MergedConfig()); 358 expect(enableObfuscation).to.be.false; 359 }); 360 }); 361 362 describe('getSelfConfigs', () => { 363 it('should create an instance with the correct properties', () => { 364 const projectConfig = { 365 obfuscationOptions: { 366 selfConfig: { 367 ruleOptions: { 368 rules: [] 369 } 370 } 371 }, 372 compileHar: true 373 }; 374 const logger = console; 375 const isTerser = false; 376 const resolver = new ObConfigResolver(projectConfig, logger, isTerser); 377 378 expect(resolver).to.be.an('object'); 379 expect(resolver.sourceObConfig).to.deep.equal(projectConfig.obfuscationOptions); 380 expect(resolver.logger).to.equal(logger); 381 expect(resolver.isHarCompiled).to.equal(projectConfig.compileHar); 382 expect(resolver.isTerser).to.equal(isTerser); 383 }); 384 385 it('should create an instance with the correct properties', () => { 386 const projectConfig = { 387 obfuscationOptions: { 388 selfConfig: { 389 ruleOptions: { 390 rules: ['./test/ut/initialization/tempNameCache.json'] 391 } 392 } 393 }, 394 compileHar: true 395 }; 396 const logger = console; 397 const isTerser = false; 398 const resolver = new ObConfigResolver(projectConfig, logger, isTerser); 399 400 expect(resolver).to.be.an('object'); 401 expect(resolver.sourceObConfig).to.deep.equal(projectConfig.obfuscationOptions); 402 expect(resolver.logger).to.equal(logger); 403 expect(resolver.isHarCompiled).to.equal(projectConfig.compileHar); 404 expect(resolver.isTerser).to.equal(isTerser); 405 }); 406 407 it('should get self configs correctly', () => { 408 const projectConfig = { 409 obfuscationOptions: { 410 selfConfig: { 411 ruleOptions: { 412 rules: ['./test/ut/initialization/tempNameCache.json'] 413 } 414 } 415 }, 416 compileHar: true 417 }; 418 const logger = console; 419 const isTerser = false; 420 const resolver = new ObConfigResolver(projectConfig, logger, isTerser); 421 const selfConfigs = new MergedConfig(); 422 423 resolver.getSelfConfigsForTest(selfConfigs); 424 425 expect(resolver).to.be.an('object'); 426 expect(resolver.sourceObConfig).to.deep.equal(projectConfig.obfuscationOptions); 427 expect(resolver.logger).to.equal(logger); 428 expect(resolver.isHarCompiled).to.equal(projectConfig.compileHar); 429 expect(resolver.isTerser).to.equal(isTerser); 430 }); 431 }); 432 433 describe('getConfigByPath', () => { 434 const projectConfig = { 435 obfuscationOptions: { 436 selfConfig: { 437 ruleOptions: { 438 rules: ['./test/testData/obfuscation/filename_obf/getConfigByPath.json'] 439 } 440 } 441 }, 442 compileHar: true 443 }; 444 const logger = console; 445 let sandbox; 446 let instance; 447 448 beforeEach(() => { 449 sandbox = sinon.createSandbox(); 450 instance = new ObConfigResolver(projectConfig, logger, true); 451 instance.logger = { error: sandbox.stub() }; 452 }); 453 454 afterEach(() => { 455 sandbox.restore(); 456 }); 457 458 it('should read file content and handle config content', () => { 459 const path = './test/testData/obfuscation/filename_obf/getConfigByPath.json'; 460 let fileContent; 461 const expectedContent = '{"key": "value"}'; 462 const configs = new MergedConfig(); 463 464 fileContent = fs.readFileSync(path, 'utf-8'); 465 instance.getConfigByPathForTest(path, configs); 466 instance.handleConfigContent(fileContent, configs, path); 467 468 expect(fileContent).to.equal(expectedContent); 469 expect(configs).to.be.an.instanceOf(MergedConfig); 470 }); 471 472 it('should log error and throw when failed to open file', () => { 473 const path = './test/testData/obfuscation/filename_obf/non-existent-file.json'; 474 const configs = new MergedConfig(); 475 const errorMessage = `Failed to open ${path}. Error message: ENOENT: no such file or directory, open '${path}'`; 476 477 sandbox.stub(fs, 'readFileSync').throws(new Error(errorMessage)); 478 479 expect(() => instance.getConfigByPath(path, configs)).to.throw(Error, errorMessage); 480 expect(instance.logger.error.calledWith(errorMessage)).to.be.false; 481 }); 482 }); 483 484 it('should return a new MergedConfig instance when sourceObConfig is not defined', function() { 485 const projectConfig = { 486 sourceObConfig: null, 487 getMergedConfig: function() { 488 let sourceObConfig = this.sourceObConfig; 489 if (!sourceObConfig) { 490 return new MergedConfig(); 491 } 492 } 493 }; 494 495 const result = projectConfig.getMergedConfig(); 496 expect(result).to.be.an.instanceOf(MergedConfig); 497 }); 498 499 describe('resolveKeepConfig', () => { 500 it('should resolve keep config correctly, starts with "!" and contains "*", not starts with "!"', () => { 501 const keepConfigs = ['!test/*/exclude.js', 'test/include.js']; 502 const configs = new MergedConfig(); 503 const configPath = './test/testData/obfuscation/keepDts/obfuscation-template.txt'; 504 505 newObConfigResolver.resolveKeepConfig(keepConfigs, configs, configPath); 506 507 expect(configs.excludeUniversalPaths).to.have.lengthOf(1); 508 expect(configs.keepUniversalPaths).to.have.lengthOf(0); 509 expect(configs.excludePathSet).to.have.lengthOf(0); 510 expect(configs.keepSourceOfPaths).to.have.lengthOf(0); 511 }); 512 513 it('should resolve keep config correctly, starts with "!" and contains "*", not starts with "!" and "?"', () => { 514 const keepConfigs = ['!test/*/exclude.js', 'test/?/include.js']; 515 const configs = new MergedConfig(); 516 const configPath = './test/testData/obfuscation/keepDts/obfuscation-template.txt'; 517 518 newObConfigResolver.resolveKeepConfig(keepConfigs, configs, configPath); 519 520 expect(configs.excludeUniversalPaths).to.have.lengthOf(1); 521 expect(configs.keepUniversalPaths).to.have.lengthOf(1); 522 expect(configs.excludePathSet).to.have.lengthOf(0); 523 expect(configs.keepSourceOfPaths).to.have.lengthOf(0); 524 }); 525 526 it('should resolve keep config correctly, both start with "!", contains "*" and "?"', () => { 527 const keepConfigs = ['!test/*/exclude.js', '!test/?/include.js']; 528 const configs = new MergedConfig(); 529 const configPath = './test/testData/obfuscation/keepDts/obfuscation-template.txt'; 530 531 newObConfigResolver.resolveKeepConfig(keepConfigs, configs, configPath); 532 533 expect(configs.excludeUniversalPaths).to.have.lengthOf(2); 534 expect(configs.keepUniversalPaths).to.have.lengthOf(0); 535 expect(configs.excludePathSet).to.have.lengthOf(0); 536 expect(configs.keepSourceOfPaths).to.have.lengthOf(0); 537 }); 538 539 it('should resolve keep config correctly, not starts with "!" and contains "*" and "?"', () => { 540 const keepConfigs = ['test/*/exclude.js', 'test/?/include.js']; 541 const configs = new MergedConfig(); 542 const configPath = './test/testData/obfuscation/keepDts/obfuscation-template.txt'; 543 544 newObConfigResolver.resolveKeepConfig(keepConfigs, configs, configPath); 545 546 expect(configs.excludeUniversalPaths).to.have.lengthOf(0); 547 expect(configs.keepUniversalPaths).to.have.lengthOf(2); 548 expect(configs.excludePathSet).to.have.lengthOf(0); 549 expect(configs.keepSourceOfPaths).to.have.lengthOf(0); 550 }); 551 552 it('should resolve keep config correctly, starts with "!", not starts with "!" and contains "*"', () => { 553 const keepConfigs = ['!test/exclude.js', 'test/*/include.js']; 554 const configs = new MergedConfig(); 555 const configPath = './test/testData/obfuscation/keepDts/obfuscation-template.txt'; 556 557 newObConfigResolver.resolveKeepConfig(keepConfigs, configs, configPath); 558 559 expect(configs.excludeUniversalPaths).to.have.lengthOf(0); 560 expect(configs.keepUniversalPaths).to.have.lengthOf(1); 561 expect(configs.excludePathSet).to.have.lengthOf(1); 562 expect(configs.keepSourceOfPaths).to.have.lengthOf(0); 563 }); 564 565 it('should resolve keep config correctly, starts with "!" and not starts with "!"', () => { 566 const keepConfigs = ['!test/exclude.js', 'test/include.js']; 567 const configs = new MergedConfig(); 568 const configPath = './test/testData/obfuscation/keepDts/obfuscation-template.txt'; 569 570 newObConfigResolver.resolveKeepConfig(keepConfigs, configs, configPath); 571 572 expect(configs.excludeUniversalPaths).to.have.lengthOf(0); 573 expect(configs.keepUniversalPaths).to.have.lengthOf(0); 574 expect(configs.excludePathSet).to.have.lengthOf(1); 575 expect(configs.keepSourceOfPaths).to.have.lengthOf(0); 576 }); 577 578 it('should resolve keep config correctly, both start with "!"', () => { 579 const keepConfigs = ['!test/exclude.js', '!test/include.js']; 580 const configs = new MergedConfig(); 581 const configPath = './test/testData/obfuscation/keepDts/obfuscation-template.txt'; 582 583 newObConfigResolver.resolveKeepConfig(keepConfigs, configs, configPath); 584 585 expect(configs.excludeUniversalPaths).to.have.lengthOf(0); 586 expect(configs.keepUniversalPaths).to.have.lengthOf(0); 587 expect(configs.excludePathSet).to.have.lengthOf(2); 588 expect(configs.keepSourceOfPaths).to.have.lengthOf(0); 589 }); 590 }); 591 592 describe('resolvePath', () => { 593 it('should return the absolute path if token is already an absolute path', () => { 594 const configPath = '/home/user/config.json'; 595 const token = '/home/user/data.txt'; 596 const result = newObConfigResolver.resolvePathForTest(configPath, token); 597 expect(result).to.equal(token); 598 }); 599 600 it('should resolve the relative path based on the config file directory', () => { 601 const configPath = '/home/user/config.json'; 602 const token = 'data.txt'; 603 const expectedResult = '/home/user/data.txt'; 604 const result = newObConfigResolver.resolvePathForTest(configPath, token); 605 expect(result).to.equal(expectedResult); 606 }); 607 }); 608 609 describe('getTokenType', () => { 610 it('should return the correct OptionType for each token', () => { 611 const tokens = [ 612 ObConfigResolver.KEEP_DTS, 613 ObConfigResolver.KEEP_GLOBAL_NAME, 614 ObConfigResolver.KEEP_PROPERTY_NAME, 615 ObConfigResolver.KEEP_FILE_NAME, 616 ObConfigResolver.KEEP_COMMENTS, 617 ObConfigResolver.DISABLE_OBFUSCATION, 618 ObConfigResolver.ENABLE_PROPERTY_OBFUSCATION, 619 ObConfigResolver.ENABLE_STRING_PROPERTY_OBFUSCATION, 620 ObConfigResolver.ENABLE_TOPLEVEL_OBFUSCATION, 621 ObConfigResolver.ENABLE_FILENAME_OBFUSCATION, 622 ObConfigResolver.ENABLE_EXPORT_OBFUSCATION, 623 ObConfigResolver.REMOVE_COMMENTS, 624 ObConfigResolver.COMPACT, 625 ObConfigResolver.REMOVE_LOG, 626 ObConfigResolver.PRINT_NAMECACHE, 627 ObConfigResolver.PRINT_KEPT_NAMES, 628 ObConfigResolver.APPLY_NAMECACHE, 629 ObConfigResolver.KEEP, 630 'unknown_token' 631 ]; 632 633 const expectedResults = [ 634 OptionTypeForTest.KEEP_DTS, 635 OptionTypeForTest.KEEP_GLOBAL_NAME, 636 OptionTypeForTest.KEEP_PROPERTY_NAME, 637 OptionTypeForTest.KEEP_FILE_NAME, 638 OptionTypeForTest.KEEP_COMMENTS, 639 OptionTypeForTest.DISABLE_OBFUSCATION, 640 OptionTypeForTest.ENABLE_PROPERTY_OBFUSCATION, 641 OptionTypeForTest.ENABLE_STRING_PROPERTY_OBFUSCATION, 642 OptionTypeForTest.ENABLE_TOPLEVEL_OBFUSCATION, 643 OptionTypeForTest.ENABLE_FILENAME_OBFUSCATION, 644 OptionTypeForTest.ENABLE_EXPORT_OBFUSCATION, 645 OptionTypeForTest.REMOVE_COMMENTS, 646 OptionTypeForTest.COMPACT, 647 OptionTypeForTest.REMOVE_LOG, 648 OptionTypeForTest.PRINT_NAMECACHE, 649 OptionTypeForTest.PRINT_KEPT_NAMES, 650 OptionTypeForTest.APPLY_NAMECACHE, 651 OptionTypeForTest.KEEP, 652 OptionTypeForTest.NONE 653 ]; 654 655 for (let i = 0; i < tokens.length; i++) { 656 const result = newObConfigResolver.getTokenTypeForTest(tokens[i]); 657 expect(result).to.equal(expectedResults[i]); 658 } 659 }); 660 }); 661 662 describe('handleConfigContent', () => { 663 it('should handle config content correctly', () => { 664 const configs: MergedConfig = new MergedConfig(); 665 configs.options = new ObOptionsForTest(); 666 667 const configPath = './test/testData/obfuscation/keepDts/obfuscation-template.txt'; 668 const data = ` 669 #This is a comment 670 -none, 671 -keep obfuscation-template.txt, 672 -keep-dts, 673 -keep-global-name, 674 -keep-property-name, 675 -keep-file-name, 676 -keep-comments, 677 -disable-obfuscation, 678 -enable-property-obfuscation, 679 -enable-string-property-obfuscation, 680 -enable-toplevel-obfuscation, 681 -enable-filename-obfuscation, 682 -enable-export-obfuscation, 683 -remove-comments, 684 -compact, 685 -remove-log, 686 -print-namecache obfuscation-template.txt, 687 -print-kept-names, 688 -apply-namecache obfuscation-template.txt 689 `; 690 691 newObConfigResolver.handleConfigContentForTest(data, configs, configPath); 692 693 expect(configs.options.disableObfuscation).to.be.true; 694 expect(configs.options.enablePropertyObfuscation).to.be.true; 695 expect(configs.options.enableStringPropertyObfuscation).to.be.true; 696 expect(configs.options.enableToplevelObfuscation).to.be.true; 697 expect(configs.options.removeComments).to.be.true; 698 expect(configs.options.enableFileNameObfuscation).to.be.true; 699 expect(configs.options.enableExportObfuscation).to.be.true; 700 expect(configs.options.compact).to.be.true; 701 expect(configs.options.removeLog).to.be.true; 702 }); 703 }); 704 705 describe('1: test Api getSystemApiCache', function() { 706 it('1-1: test getSystemApiCache: -enable-property-obfuscation', function () { 707 let obfuscationCacheDir = path.join(OBFUSCATE_TESTDATA_DIR, 'property'); 708 let obfuscationOptions = { 709 'selfConfig': { 710 'ruleOptions': { 711 'enable': true, 712 'rules': [ 713 path.join(OBFUSCATE_TESTDATA_DIR, 'property/property.txt') 714 ] 715 }, 716 'consumerRules': [], 717 }, 718 'dependencies': { 719 'libraries': [], 720 'hars': [] 721 }, 722 'obfuscationCacheDir': obfuscationCacheDir, 723 'sdkApis': [ 724 path.join(OBFUSCATE_TESTDATA_DIR, 'system_api.d.ts') 725 ] 726 }; 727 let projectConfig = { 728 obfuscationOptions, 729 compileHar: false 730 }; 731 const obConfig: ObConfigResolver = new ObConfigResolver(projectConfig, undefined); 732 obConfig.resolveObfuscationConfigs(); 733 const reservedSdkApiForProp = UnobfuscationCollections.reservedSdkApiForProp; 734 const reservedSdkApiForGlobal = UnobfuscationCollections.reservedSdkApiForGlobal; 735 736 expect(reservedSdkApiForProp.size == 12).to.be.true; 737 expect(reservedSdkApiForProp.has('TestClass')).to.be.true; 738 expect(reservedSdkApiForProp.has('para1')).to.be.true; 739 expect(reservedSdkApiForProp.has('para2')).to.be.true; 740 expect(reservedSdkApiForProp.has('foo')).to.be.true; 741 expect(reservedSdkApiForProp.has('TestFunction')).to.be.true; 742 expect(reservedSdkApiForProp.has('funcPara1')).to.be.true; 743 expect(reservedSdkApiForProp.has('funcPara2')).to.be.true; 744 expect(reservedSdkApiForProp.has('ns')).to.be.true; 745 expect(reservedSdkApiForProp.has('NavigationBuilderRegister')).to.be.true; 746 expect(reservedSdkApiForProp.has('ViewV2')).to.be.true; 747 expect(reservedSdkApiForProp.has('initParam')).to.be.true; 748 expect(reservedSdkApiForProp.has('updateParam')).to.be.true; 749 expect(reservedSdkApiForGlobal.size == 0).to.be.true; 750 UnobfuscationCollections.clear(); 751 752 let systemApiPath = obfuscationCacheDir + '/systemApiCache.json'; 753 const data = fs.readFileSync(systemApiPath, 'utf8'); 754 const systemApiContent = JSON.parse(data); 755 756 expect(systemApiContent.ReservedPropertyNames.length == 12).to.be.true; 757 expect(systemApiContent.ReservedPropertyNames.includes('TestClass')).to.be.true; 758 expect(systemApiContent.ReservedPropertyNames.includes('para1')).to.be.true; 759 expect(systemApiContent.ReservedPropertyNames.includes('para2')).to.be.true; 760 expect(systemApiContent.ReservedPropertyNames.includes('foo')).to.be.true; 761 expect(systemApiContent.ReservedPropertyNames.includes('TestFunction')).to.be.true; 762 expect(systemApiContent.ReservedPropertyNames.includes('funcPara1')).to.be.true; 763 expect(systemApiContent.ReservedPropertyNames.includes('funcPara2')).to.be.true; 764 expect(systemApiContent.ReservedPropertyNames.includes('ns')).to.be.true; 765 expect(systemApiContent.ReservedPropertyNames.includes('NavigationBuilderRegister')).to.be.true; 766 expect(systemApiContent.ReservedPropertyNames.includes('ViewV2')).to.be.true; 767 expect(systemApiContent.ReservedPropertyNames.includes('initParam')).to.be.true; 768 expect(systemApiContent.ReservedPropertyNames.includes('updateParam')).to.be.true; 769 expect(systemApiContent.ReservedGlobalNames == undefined).to.be.true; 770 771 fs.unlinkSync(systemApiPath); 772 }); 773 774 it('1-2: test getSystemApiCache: -enable-export-obfuscation', function () { 775 let obfuscationCacheDir = path.join(OBFUSCATE_TESTDATA_DIR, 'export'); 776 let obfuscationOptions = { 777 'selfConfig': { 778 'ruleOptions': { 779 'enable': true, 780 'rules': [ 781 path.join(OBFUSCATE_TESTDATA_DIR, 'export/export.txt') 782 ] 783 }, 784 'consumerRules': [], 785 }, 786 'dependencies': { 787 'libraries': [], 788 'hars': [] 789 }, 790 'obfuscationCacheDir': obfuscationCacheDir, 791 'sdkApis': [ 792 path.join(OBFUSCATE_TESTDATA_DIR, 'system_api.d.ts') 793 ] 794 }; 795 let projectConfig = { 796 obfuscationOptions, 797 compileHar: false 798 }; 799 const obConfig: ObConfigResolver = new ObConfigResolver(projectConfig, undefined); 800 obConfig.resolveObfuscationConfigs(); 801 const reservedSdkApiForProp = UnobfuscationCollections.reservedSdkApiForProp; 802 const reservedSdkApiForGlobal = UnobfuscationCollections.reservedSdkApiForGlobal; 803 804 expect(reservedSdkApiForProp.size == 0).to.be.true; 805 expect(reservedSdkApiForGlobal.size == 0).to.be.true; 806 UnobfuscationCollections.clear(); 807 808 let systemApiPath = obfuscationCacheDir + '/systemApiCache.json'; 809 const noSystemApi = fs.existsSync(systemApiPath); 810 811 expect(noSystemApi).to.be.false; 812 }); 813 814 it('1-3: test getSystemApiCache: -enable-export-obfuscation -enable-toplevel-obfuscation', function () { 815 let obfuscationCacheDir = path.join(OBFUSCATE_TESTDATA_DIR, 'export_toplevel'); 816 let obfuscationOptions = { 817 'selfConfig': { 818 'ruleOptions': { 819 'enable': true, 820 'rules': [ 821 path.join(OBFUSCATE_TESTDATA_DIR, 'export_toplevel/export_toplevel.txt') 822 ] 823 }, 824 'consumerRules': [], 825 }, 826 'dependencies': { 827 'libraries': [], 828 'hars': [] 829 }, 830 'obfuscationCacheDir': obfuscationCacheDir, 831 'sdkApis': [ 832 path.join(OBFUSCATE_TESTDATA_DIR, 'system_api.d.ts') 833 ] 834 }; 835 let projectConfig = { 836 obfuscationOptions, 837 compileHar: false 838 }; 839 const obConfig: ObConfigResolver = new ObConfigResolver(projectConfig, undefined); 840 obConfig.resolveObfuscationConfigs(); 841 const reservedSdkApiForProp = UnobfuscationCollections.reservedSdkApiForProp; 842 const reservedSdkApiForGlobal = UnobfuscationCollections.reservedSdkApiForGlobal; 843 844 expect(reservedSdkApiForProp.size == 0).to.be.true; 845 expect(reservedSdkApiForGlobal.size == 3).to.be.true; 846 expect(reservedSdkApiForGlobal.has('TestClass')).to.be.true; 847 expect(reservedSdkApiForGlobal.has('TestFunction')).to.be.true; 848 expect(reservedSdkApiForGlobal.has('ns')).to.be.true; 849 UnobfuscationCollections.clear(); 850 851 let systemApiPath = obfuscationCacheDir + '/systemApiCache.json'; 852 const data = fs.readFileSync(systemApiPath, 'utf8'); 853 const systemApiContent = JSON.parse(data); 854 855 expect(systemApiContent.ReservedPropertyNames == undefined).to.be.true; 856 expect(systemApiContent.ReservedGlobalNames.length == 3).to.be.true; 857 expect(systemApiContent.ReservedGlobalNames.includes('TestClass')).to.be.true; 858 expect(systemApiContent.ReservedGlobalNames.includes('TestFunction')).to.be.true; 859 expect(systemApiContent.ReservedGlobalNames.includes('ns')).to.be.true; 860 861 fs.unlinkSync(systemApiPath); 862 }); 863 }); 864 }); 865 866 describe('collectResevedFileNameInIDEConfig', () => { 867 let collectPathReservedStringStub; 868 869 beforeEach(function() { 870 collectPathReservedStringStub = sinon.stub(FileUtils, 'collectPathReservedString'); 871 collectPathReservedStringStub.callsFake((filePath, reservedArray) => reservedArray.push(filePath)); 872 }); 873 874 afterEach(function() { 875 collectPathReservedStringStub.restore(); 876 projectConfig.compileShared = false; 877 projectConfig.byteCodeHar = false; 878 projectConfig.aceModuleJsonPath = ''; 879 }); 880 881 const ohPackagePath = './test/ut/initialization/testOhPackagePath.json'; 882 let projectConfig = { 883 aceModuleJsonPath: '', 884 projectPath: 'path/to/project', 885 cachePath: 'path/to/cache', 886 compileShared: false, 887 byteCodeHar: false, 888 aceModuleBuild: 'path/to/build', 889 } 890 const entryArray = ['path/to/entry1', 'path/to/entry2']; 891 const modulePathMap = { 892 module1: 'path/to/module1', 893 module2: 'path/to/module2', 894 }; 895 896 it('should collect reserved file names from entryArray and projectConfig', () => { 897 const result = collectResevedFileNameInIDEConfig('', projectConfig, undefined, entryArray); 898 expect(result).to.deep.equal(['path/to/entry1', 'path/to/entry2','path/to/project','path/to/cache']); 899 }); 900 it('should collect reserved file names from modulePathMap and projectConfig', () => { 901 projectConfig.compileShared = true; 902 const result = collectResevedFileNameInIDEConfig('', projectConfig, modulePathMap, []); 903 expect(result).to.deep.equal(['path/to/module1', 'path/to/module2','module1','module2','path/to/build','etsFortgz','path/to/project','path/to/cache']); 904 }); 905 it('should collect reserved file names from ohPackagePath and projectConfig', () => { 906 projectConfig.byteCodeHar = true; 907 const result = collectResevedFileNameInIDEConfig(ohPackagePath, projectConfig, undefined, []); 908 expect(result).to.deep.equal(['path/to/main', 'path/to/types','path/to/build','etsFortgz','path/to/project','path/to/cache']); 909 }); 910 it('should collect reserved file names from moduleJsonPath and projectConfig', () => { 911 projectConfig.aceModuleJsonPath = "./test/ut/initialization/testModuleJsonPath_0.json"; 912 const hasSrcEntry = collectResevedFileNameInIDEConfig('', projectConfig, undefined, []); 913 expect(hasSrcEntry).to.deep.equal(['path/to/srcEntry','path/to/project','path/to/cache']); 914 915 projectConfig.aceModuleJsonPath = "./test/ut/initialization/testModuleJsonPath_1.json"; 916 const noSrcEntry = collectResevedFileNameInIDEConfig('', projectConfig, undefined, []); 917 expect(noSrcEntry).to.deep.equal(['path/to/project','path/to/cache']); 918 }); 919 }); 920 921 describe('readNameCache', () => { 922 let tempFilePath; 923 let testData; 924 let fsWriteFileSyncStub; 925 let fsUnlinkSyncStub; 926 let logger = { 927 error: (message: string) => console.error(message), 928 }; 929 let PropCollections; 930 let renameFileNameModule; 931 932 beforeEach(() => { 933 PropCollections = { 934 historyMangledTable: {}, 935 }; 936 renameFileNameModule = { 937 historyFileNameMangledTable: {}, 938 }; 939 940 tempFilePath = './test/ut/initialization/tempNameCache.json'; 941 testData = { 942 compileSdkVersion: '1.0.0', 943 PropertyCache: { key1: 'value1', key2: 'value2' }, 944 FileNameCache: { key3: 'value3', key4: 'value4' }, 945 extraKey: '', 946 }; 947 948 fsWriteFileSyncStub = sinon.stub(fs, 'writeFileSync').callsFake((path, data) => {}); 949 fsUnlinkSyncStub = sinon.stub(fs, 'unlinkSync').callsFake((path) => {}); 950 }); 951 952 afterEach(() => { 953 fsWriteFileSyncStub.restore(); 954 fsUnlinkSyncStub.restore(); 955 }); 956 957 it('should read and parse the name cache file correctly', () => { 958 readNameCache(tempFilePath, logger); 959 960 expect(nameCacheMap.get('extraKey')).to.equal(''); 961 }); 962 }); 963 964 describe('readNameCache', () => { 965 let fsReadFileSyncStub; 966 let logger; 967 const testPath = './test/ut/initialization/tempNameCache.json'; 968 969 beforeEach(() => { 970 fsReadFileSyncStub = sinon.stub(fs, 'readFileSync').returns('{"compileSdkVersion":"1.0","PropertyCache":{},"FileNameCache":{}}'); 971 logger = { error: sinon.spy() }; 972 }); 973 974 afterEach(() => { 975 fsReadFileSyncStub.restore(); 976 }); 977 978 it('should read the name cache file and parse its content', () => { 979 readNameCache(testPath, logger); 980 expect(PropCollections.historyMangledTable).to.deep.equal(new Map()); 981 expect(renameFileNameModule.historyFileNameMangledTable).to.deep.equal(new Map()); 982 expect(nameCacheMap.get('compileSdkVersion')).to.be.undefined; 983 expect(logger.error.called).to.be.false; 984 }); 985 986 it('should handle errors when reading the file', () => { 987 const mockLogger = { 988 error: (message: string) => console.error(message), 989 }; 990 991 const nonExistentFilePath = './test/ut/initialization/nonExistentFile.json'; 992 readNameCache(nonExistentFilePath, mockLogger); 993 fsReadFileSyncStub.throws(new Error('Test error')); 994 readNameCache(testPath, logger); 995 expect(logger.error.calledWith(`Failed to open ${nonExistentFilePath}. Error message: Test error`)).to.be.false; 996 }); 997 }); 998 999 describe('handleUniversalPathInObf', () => { 1000 it('should handle universal paths correctly', () => { 1001 const mergedObConfig: MergedConfig = { 1002 options: new ObOptionsForTest(), 1003 reservedPropertyNames: [], 1004 reservedGlobalNames: [], 1005 reservedNames: [], 1006 reservedFileNames: [], 1007 keepComments: [], 1008 keepSourceOfPaths: [], 1009 universalReservedPropertyNames: [], 1010 universalReservedGlobalNames: [], 1011 keepUniversalPaths: [/test\.js$/], 1012 excludeUniversalPaths: [/exclude\.js$/], 1013 excludePathSet: new Set(), 1014 merge: () => {}, 1015 sortAndDeduplicate: () => {}, 1016 serializeMergedConfig: () => { 1017 return JSON.stringify(this); 1018 } 1019 }; 1020 const allSourceFilePaths = new Set([ 1021 'test.js', 1022 'exclude.js', 1023 'other.js', 1024 ]); 1025 1026 handleUniversalPathInObf(mergedObConfig, allSourceFilePaths); 1027 expect(mergedObConfig.keepSourceOfPaths).to.deep.equal(['test.js']); 1028 expect(mergedObConfig.excludePathSet).to.deep.equal(new Set(['exclude.js'])); 1029 }); 1030 1031 it('should return early if mergedObConfig is not provided or both keepUniversalPaths and excludeUniversalPaths are empty', () => { 1032 const mergedObConfig: MergedConfig = { 1033 options: new ObOptionsForTest(), 1034 reservedPropertyNames: [], 1035 reservedGlobalNames: [], 1036 reservedNames: [], 1037 reservedFileNames: [], 1038 keepComments: [], 1039 keepSourceOfPaths: [], 1040 universalReservedPropertyNames: [], 1041 universalReservedGlobalNames: [], 1042 keepUniversalPaths: [], 1043 excludeUniversalPaths: [], 1044 excludePathSet: new Set(), 1045 merge: () => {}, 1046 sortAndDeduplicate: () => {}, 1047 serializeMergedConfig: () => { 1048 return JSON.stringify(this); 1049 } 1050 }; 1051 const allSourceFilePaths = new Set([]); 1052 const result = handleUniversalPathInObf(mergedObConfig, allSourceFilePaths); 1053 1054 expect(result).to.be.undefined; 1055 }); 1056 }); 1057 1058 describe('getArkguardNameCache', () => { 1059 it('should return a JSON string with the correct structure', () => { 1060 const enablePropertyObfuscation = true; 1061 const enableFileNameObfuscation = true; 1062 const sdkVersion = '1.0.0'; 1063 const entryPackageInfo = 'packageInfo'; 1064 1065 const result = getArkguardNameCache(enablePropertyObfuscation, enableFileNameObfuscation, false, sdkVersion, entryPackageInfo); 1066 1067 try { 1068 JSON.parse(result); 1069 // If no error is thrown, the result is a valid JSON string 1070 console.log('Test passed: getArkguardNameCache returns a valid JSON string'); 1071 } catch (error) { 1072 console.error('Test failed: getArkguardNameCache does not return a valid JSON string'); 1073 } 1074 }); 1075 1076 it('should include the correct compileSdkVersion and entryPackageInfo', () => { 1077 const enablePropertyObfuscation = false; 1078 const enableFileNameObfuscation = false; 1079 const sdkVersion = '2.0.0'; 1080 const entryPackageInfo = 'anotherPackageInfo'; 1081 1082 const result = getArkguardNameCache(enablePropertyObfuscation, enableFileNameObfuscation, false, sdkVersion, entryPackageInfo); 1083 const parsedResult = JSON.parse(result); 1084 1085 expect(parsedResult.compileSdkVersion).to.equal(sdkVersion); 1086 expect(parsedResult.entryPackageInfo).to.equal(entryPackageInfo); 1087 }); 1088 1089 it('PropertyCache exists when enable export obfuscation', () => { 1090 const enablePropertyObfuscation = false; 1091 const enableFileNameObfuscation = false; 1092 const enableExportObfuscation = true; 1093 const sdkVersion = '2.0.0'; 1094 const entryPackageInfo = 'anotherPackageInfo'; 1095 1096 PropCollections.historyMangledTable.set("key1", "value1"); 1097 PropCollections.historyMangledTable.set("key2", "value2"); 1098 PropCollections.globalMangledTable.set("key3", "value3"); 1099 PropCollections.globalMangledTable.set("key4", "value4"); 1100 const result = getArkguardNameCache(enablePropertyObfuscation, enableFileNameObfuscation, enableExportObfuscation, sdkVersion, entryPackageInfo); 1101 const parsedResult = JSON.parse(result); 1102 PropCollections.historyMangledTable.clear(); 1103 PropCollections.globalMangledTable.clear(); 1104 expect('PropertyCache' in parsedResult).to.be.true; 1105 expect(parsedResult.PropertyCache.key1 === "value1").to.be.true; 1106 expect(parsedResult.PropertyCache.key2 === "value2").to.be.true; 1107 expect(parsedResult.PropertyCache.key3 === "value3").to.be.true; 1108 expect(parsedResult.PropertyCache.key4 === "value4").to.be.true; 1109 }); 1110 }); 1111 1112 describe('fillNameCache', function() { 1113 it('should correctly fill the name cache with the given table entries', function() { 1114 const table = new Map([ 1115 ['key1', 'value1'], 1116 ['key2', 'value2'], 1117 ['key3', 'value3'] 1118 ]); 1119 const nameCache = new Map(); 1120 1121 fillNameCache(table, nameCache); 1122 1123 assert.deepEqual(nameCache, table); 1124 }); 1125 1126 it('should handle empty tables gracefully', function() { 1127 const table = new Map(); 1128 const nameCache = new Map(); 1129 1130 fillNameCache(table, nameCache); 1131 1132 assert.deepEqual(nameCache, table); 1133 }); 1134 }); 1135 1136 describe('writeObfuscationNameCache', () => { 1137 let existsSyncSpy; 1138 let mkdirSyncSpy; 1139 let writeFileSyncSpy; 1140 1141 beforeEach(function() { 1142 existsSyncSpy = sinon.spy(fs, 'existsSync'); 1143 mkdirSyncSpy = sinon.spy(fs, 'mkdirSync'); 1144 writeFileSyncSpy = sinon.spy(fs, 'writeFileSync'); 1145 }); 1146 1147 afterEach(function() { 1148 existsSyncSpy.restore(); 1149 mkdirSyncSpy.restore(); 1150 writeFileSyncSpy.restore(); 1151 }); 1152 1153 it('should not write cache if projectConfig.arkObfuscator is false', () => { 1154 const projectConfig = { 1155 arkObfuscator: false, 1156 obfuscationMergedObConfig: { 1157 options: { 1158 enablePropertyObfuscation: true, 1159 enableFileNameObfuscation: true, 1160 }, 1161 }, 1162 etsLoaderVersion: '1.0.0', 1163 }; 1164 const entryPackageInfo = 'testEntryPackageInfo'; 1165 const obfuscationCacheDir = 'testCacheDir'; 1166 const printNameCache = 'testPrintNameCache'; 1167 1168 writeObfuscationNameCache(projectConfig, entryPackageInfo, obfuscationCacheDir, printNameCache); 1169 1170 expect(existsSyncSpy.called).to.be.false; 1171 expect(mkdirSyncSpy.called).to.be.false; 1172 expect(writeFileSyncSpy.called).to.be.false; 1173 }); 1174 it('should write cache to obfuscationCacheDir if provided', () => { 1175 const projectConfig = { 1176 arkObfuscator: true, 1177 obfuscationMergedObConfig: { 1178 options: { 1179 enablePropertyObfuscation: true, 1180 enableFileNameObfuscation: true, 1181 enableExportObfusaction: true 1182 }, 1183 }, 1184 etsLoaderVersion: '1.0.0', 1185 }; 1186 const entryPackageInfo = 'testEntryPackageInfo'; 1187 const obfuscationCacheDir = './test/ut/initialization/testObfuscationCacheDir'; 1188 const printNameCache = ''; 1189 writeObfuscationNameCache(projectConfig, entryPackageInfo, obfuscationCacheDir, printNameCache); 1190 const defaultNameCachePath: string = path.join(obfuscationCacheDir, 'nameCache.json'); 1191 const expectedContent = { 1192 "extraKey": "", 1193 "compileSdkVersion": "1.0.0", 1194 "entryPackageInfo": "testEntryPackageInfo", 1195 "PropertyCache": {}, 1196 "FileNameCache": {} 1197 } 1198 const jsonData = fs.readFileSync(defaultNameCachePath,'utf-8'); 1199 const result = JSON.parse(jsonData); 1200 expect(result).to.deep.equal(expectedContent); 1201 fs.unlinkSync(defaultNameCachePath); 1202 fs.rmdirSync(path.dirname(defaultNameCachePath)); 1203 }); 1204 it('should write cache to printNameCache if provided', () => { 1205 const projectConfig = { 1206 arkObfuscator: true, 1207 obfuscationMergedObConfig: { 1208 options: { 1209 enablePropertyObfuscation: true, 1210 enableFileNameObfuscation: true, 1211 }, 1212 }, 1213 etsLoaderVersion: '1.0.0', 1214 }; 1215 const entryPackageInfo = 'testEntryPackageInfo'; 1216 const obfuscationCacheDir = ''; 1217 const printNameCache = './test/ut/initialization/printNameCache.json'; 1218 writeObfuscationNameCache(projectConfig, entryPackageInfo, obfuscationCacheDir, printNameCache); 1219 const expectedContent = { 1220 "extraKey": "", 1221 "compileSdkVersion": "1.0.0", 1222 "entryPackageInfo": "testEntryPackageInfo", 1223 "PropertyCache": {}, 1224 "FileNameCache": {} 1225 } 1226 const jsonData = fs.readFileSync(printNameCache,'utf-8'); 1227 const result = JSON.parse(jsonData); 1228 expect(result).to.deep.equal(expectedContent); 1229 expect(existsSyncSpy.called).to.be.false; 1230 expect(mkdirSyncSpy.called).to.be.false; 1231 fs.unlinkSync(printNameCache); 1232 }); 1233 }); 1234 1235 describe('enableObfuscatedFilePathConfig', () => { 1236 it('should return false if in debug mode or no obfuscation config', () => { 1237 const projectConfig = { 1238 obfuscationMergedObConfig: null, 1239 buildMode: 'debug' 1240 }; 1241 const result = enableObfuscatedFilePathConfig(true, projectConfig); 1242 expect(result).to.be.false; 1243 }); 1244 1245 it('should return false if obfuscation is disabled or file name obfuscation is not enabled', () => { 1246 const projectConfig = { 1247 obfuscationMergedObConfig: { 1248 options: { 1249 disableObfuscation: true, 1250 enableFileNameObfuscation: false, 1251 }, 1252 }, 1253 buildMode: 'debug' 1254 }; 1255 const result = enableObfuscatedFilePathConfig(false, projectConfig); 1256 expect(result).to.be.false; 1257 }); 1258 1259 it('should return true if all conditions are met', () => { 1260 const projectConfig = { 1261 obfuscationMergedObConfig: { 1262 options: { 1263 disableObfuscation: false, 1264 enableFileNameObfuscation: true, 1265 }, 1266 }, 1267 buildMode: 'not debug' 1268 }; 1269 const result = enableObfuscatedFilePathConfig(false, projectConfig); 1270 expect(result).to.be.true; 1271 }); 1272 }); 1273 1274 describe('handleObfuscatedFilePath', () => { 1275 it('should return the original file path if obfuscation is not enabled', () => { 1276 const filePath = '/path/to/file.js'; 1277 const isPackageModules = false; 1278 const projectConfig = { 1279 enableFileNameObfuscation: false, 1280 buildMode: 'debug' 1281 }; 1282 1283 const result = handleObfuscatedFilePath(filePath, isPackageModules, projectConfig); 1284 1285 expect(result).to.equal(filePath); 1286 }); 1287 1288 it('should return the original file path if obfuscation is not enabled', () => { 1289 const filePath = '/path/to/file.txt'; 1290 const isPackageModules = false; 1291 const projectConfig = { 1292 obfuscationMergedObConfig: null, 1293 buildMode: 'debug' 1294 }; 1295 const result = handleObfuscatedFilePath(filePath, isPackageModules, projectConfig); 1296 expect(result).to.equal(filePath); 1297 }); 1298 1299 it('should return the original file path if obfuscation is not enabled', () => { 1300 const filePath = '/path/to/file.txt'; 1301 const isPackageModules = false; 1302 const projectConfig = { 1303 obfuscationMergedObConfig: null, 1304 buildMode: 'not debug' 1305 }; 1306 const result = handleObfuscatedFilePath(filePath, isPackageModules, projectConfig); 1307 expect(result).to.equal(filePath); 1308 }); 1309 1310 it('should return the unix formatted file path if obfuscation is enabled and is a package module', () => { 1311 const filePath = '/path/to/file.js'; 1312 const isPackageModules = true; 1313 const projectConfig = { 1314 obfuscationMergedObConfig: { 1315 options: { 1316 disableObfuscation: false, 1317 enableFileNameObfuscation: true, 1318 }, 1319 }, 1320 buildMode: "not Debug" 1321 }; 1322 1323 const result = handleObfuscatedFilePath(filePath, isPackageModules, projectConfig); 1324 1325 expect(result).to.equal(FileUtils.toUnixPath(filePath)); 1326 }); 1327 1328 it('should return the unix formatted file path if obfuscation is enabled and is a package module', () => { 1329 const filePath = '/path/to/file.js'; 1330 const isPackageModules = true; 1331 const projectConfig = { 1332 obfuscationMergedObConfig: { 1333 options: { 1334 disableObfuscation: false, 1335 enableFileNameObfuscation: true, 1336 }, 1337 }, 1338 buildMode: "" 1339 }; 1340 1341 const result = handleObfuscatedFilePath(filePath, isPackageModules, projectConfig); 1342 1343 expect(result).to.equal(FileUtils.toUnixPath(filePath)); 1344 }); 1345 }); 1346 1347 describe('enableObfuscateFileName', () => { 1348 it('should return false if obfuscation is not enabled', () => { 1349 const isPackageModules = false; 1350 const projectConfig = { 1351 obfuscationMergedObConfig: null, 1352 buildMode: "not Debug" 1353 }; 1354 const result = enableObfuscateFileName(isPackageModules, projectConfig); 1355 expect(result).to.be.false; 1356 }); 1357 1358 it('should return true if obfuscation is enabled and not a package module', () => { 1359 const isPackageModules = false; 1360 const projectConfig = { 1361 obfuscationMergedObConfig: { 1362 options: { 1363 disableObfuscation: false, 1364 enableFileNameObfuscation: true, 1365 }, 1366 }, 1367 buildMode: "not Debug" 1368 }; 1369 const result = enableObfuscateFileName(isPackageModules, projectConfig); 1370 1371 expect(result).to.be.true; 1372 }); 1373 1374 it('should return false if obfuscation is enabled and is a package module', () => { 1375 const isPackageModules = true; 1376 const projectConfig = { 1377 obfuscationMergedObConfig: { 1378 options: { 1379 disableObfuscation: false, 1380 enableFileNameObfuscation: true, 1381 }, 1382 }, 1383 buildMode: "Debug" 1384 }; 1385 const result = enableObfuscateFileName(isPackageModules, projectConfig); 1386 expect(result).to.be.false; 1387 }); 1388 1389 it('should return false if obfuscation is enabled and is a package module', () => { 1390 const isPackageModules = true; 1391 const projectConfig = { 1392 obfuscationMergedObConfig: { 1393 options: { 1394 disableObfuscation: false, 1395 enableFileNameObfuscation: false, 1396 }, 1397 }, 1398 buildMode: "Debug" 1399 }; 1400 const result = enableObfuscateFileName(isPackageModules, projectConfig); 1401 expect(result).to.be.false; 1402 }); 1403 1404 it('should return false if obfuscation is enabled and is a package module', () => { 1405 const isPackageModules = true; 1406 const projectConfig = { 1407 obfuscationMergedObConfig: {}, 1408 buildMode: "Debug" 1409 }; 1410 const result = enableObfuscateFileName(isPackageModules, projectConfig); 1411 expect(result).to.be.false; 1412 }); 1413 1414 it('should return false if obfuscation is enabled and is a package module', () => { 1415 const isPackageModules = true; 1416 const projectConfig = { 1417 obfuscationMergedObConfig: null, 1418 buildMode: "Debug" 1419 }; 1420 const result = enableObfuscateFileName(isPackageModules, projectConfig); 1421 expect(result).to.be.false; 1422 }); 1423 1424 it('should return false if obfuscation is enabled and is a package module', () => { 1425 const isPackageModules = true; 1426 const projectConfig = { 1427 obfuscationMergedObConfig: undefined, 1428 buildMode: "Debug" 1429 }; 1430 const result = enableObfuscateFileName(isPackageModules, projectConfig); 1431 expect(result).to.be.false; 1432 }); 1433 1434 it('should return false if obfuscation is enabled and is a package module', () => { 1435 const isPackageModules = true; 1436 const projectConfig = { 1437 obfuscationMergedObConfig: { 1438 options: { 1439 disableObfuscation: false, 1440 enableFileNameObfuscation: true, 1441 }, 1442 }, 1443 buildMode: "not Debug" 1444 }; 1445 const result = enableObfuscateFileName(isPackageModules, projectConfig); 1446 expect(result).to.be.false; 1447 }); 1448 1449 it('should return false if obfuscation is enabled and is a package module', () => { 1450 const isPackageModules = true; 1451 const projectConfig = { 1452 obfuscationMergedObConfig: { 1453 options: { 1454 disableObfuscation: false, 1455 enableFileNameObfuscation: false, 1456 }, 1457 }, 1458 buildMode: "not Debug" 1459 }; 1460 const result = enableObfuscateFileName(isPackageModules, projectConfig); 1461 expect(result).to.be.false; 1462 }); 1463 1464 it('should return false if obfuscation is enabled and is a package module', () => { 1465 const isPackageModules = true; 1466 const projectConfig = { 1467 obfuscationMergedObConfig: { 1468 options: { 1469 disableObfuscation: false, 1470 enableFileNameObfuscation: false, 1471 }, 1472 }, 1473 buildMode: "not Debug" 1474 }; 1475 const result = enableObfuscateFileName(isPackageModules, projectConfig); 1476 expect(result).to.be.false; 1477 }); 1478 1479 it('should return false if obfuscation is enabled and is a package module', () => { 1480 const isPackageModules = true; 1481 const projectConfig = { 1482 obfuscationMergedObConfig: { 1483 options: { 1484 disableObfuscation: false, 1485 enableFileNameObfuscation: true, 1486 }, 1487 }, 1488 buildMode: "not Debug" 1489 }; 1490 const result = enableObfuscateFileName(isPackageModules, projectConfig); 1491 expect(result).to.be.false; 1492 }); 1493 }); 1494 1495 describe('getRelativeSourcePath', () => { 1496 it('should return the relative path of a file within the project root', () => { 1497 const filePath = '/Users/user/project/src/components/Button.js'; 1498 const projectRootPath = '/Users/user/project'; 1499 const expectedRelativePath = 'src/components/Button.js'; 1500 1501 const result = getRelativeSourcePath(filePath, projectRootPath, ''); 1502 expect(result).to.equal(expectedRelativePath); 1503 }); 1504 1505 it('should return the relative path of a file within a specified project path', () => { 1506 const filePath = '/Users/user/project/src/components/Button.js'; 1507 const belongProjectPath = '/Users/user/project/src'; 1508 const expectedRelativePath = 'components/Button.js'; 1509 1510 const result = getRelativeSourcePath(filePath, '', belongProjectPath); 1511 expect(result).to.equal(expectedRelativePath); 1512 }); 1513 1514 it('should return the original path if no project root or belong project path is provided', () => { 1515 const filePath = '/Users/user/project/src/components/Button.js'; 1516 const expectedRelativePath = filePath; 1517 1518 const result = getRelativeSourcePath(filePath, '', ''); 1519 expect(result).to.equal(expectedRelativePath); 1520 }); 1521 }); 1522}); 1523