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