1/* 2 * Copyright (c) 2023 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 16import { expect } from 'chai'; 17import mocha from 'mocha'; 18import fs from "fs"; 19import path from "path"; 20import MagicString from 'magic-string'; 21 22import { 23 getBuildModeInLowerCase, 24 getPackageInfo, 25 genSourceMapFileName, 26 isOhModules, 27 isEs2Abc, 28 writeTerserObfuscatedSourceCode 29} from '../../../lib/ark_utils'; 30import { 31 DEBUG, 32 RELEASE, 33 OH_MODULES, 34 EXTNAME_TS, 35 EXTNAME_JS, 36 EXTNAME_ETS, 37 OBFUSCATION_TOOL 38} from '../../../lib/fast_build/ark_compiler/common/ark_define'; 39import RollUpPluginMock from '../mock/rollup_mock/rollup_plugin_mock'; 40import { 41 BUNDLE_NAME_DEFAULT, 42 ENTRY_MODULE_NAME_DEFAULT, 43 EXTNAME_MAP, 44 ENTRYABILITY_JS 45} from '../mock/rollup_mock/common'; 46import projectConfig from '../utils/processProjectConfig'; 47import { 48 ES2ABC, 49 TS2ABC 50} from '../../../lib/pre_define'; 51import { changeFileExtension } from '../../../lib/fast_build/ark_compiler/utils'; 52import ModuleSourceFileMock from '../mock/class_mock/module_source_files_mock'; 53import { 54 genTemporaryPath, 55 toUnixPath 56} from '../../../lib/utils'; 57import { 58 ObConfigResolver, 59 MergedConfig 60} from '../../../lib/fast_build/ark_compiler/common/ob_config_resolver'; 61import { 62 utProcessArkConfig 63} from '../../../lib/fast_build/ark_compiler/common/process_ark_config'; 64import { ModuleSourceFile } from '../../../lib/fast_build/ark_compiler/module/module_source_file'; 65import { newSourceMaps } from '../../../lib/fast_build/ark_compiler/transform'; 66import { TERSER_PROCESSED_EXPECTED_CODE } from '../mock/rollup_mock/path_config'; 67 68mocha.describe('test ark_utils file api', function () { 69 mocha.before(function () { 70 this.rollup = new RollUpPluginMock(); 71 }); 72 73 mocha.after(() => { 74 delete this.rollup; 75 }); 76 77 mocha.it('1-1: test getBuildModeInLowerCase under build debug', function () { 78 this.rollup.build(); 79 const buildMode = getBuildModeInLowerCase(this.rollup.share.projectConfig); 80 expect(buildMode === DEBUG).to.be.true; 81 }); 82 83 mocha.it('1-2: test getBuildModeInLowerCase under build release', function () { 84 this.rollup.build(RELEASE); 85 const buildMode = getBuildModeInLowerCase(this.rollup.share.projectConfig); 86 expect(buildMode === RELEASE).to.be.true; 87 }); 88 89 mocha.it('1-3: test getBuildModeInLowerCase under preview debug', function () { 90 this.rollup.preview(); 91 const buildMode = getBuildModeInLowerCase(this.rollup.share.projectConfig); 92 expect(buildMode === DEBUG).to.be.true; 93 }); 94 95 mocha.it('1-4: test getBuildModeInLowerCase under hot reload debug', function () { 96 this.rollup.hotReload(); 97 const buildMode = getBuildModeInLowerCase(this.rollup.share.projectConfig); 98 expect(buildMode === DEBUG).to.be.true; 99 }); 100 101 mocha.it('2-1: test getPackageInfo under build debug', function () { 102 this.rollup.build(); 103 const returnInfo = getPackageInfo(this.rollup.share.projectConfig.aceModuleJsonPath); 104 expect(returnInfo[0] === BUNDLE_NAME_DEFAULT).to.be.true; 105 expect(returnInfo[1] === ENTRY_MODULE_NAME_DEFAULT).to.be.true; 106 }); 107 108 mocha.it('2-2: test getPackageInfo under build release', function () { 109 this.rollup.build(RELEASE); 110 const returnInfo = getPackageInfo(this.rollup.share.projectConfig.aceModuleJsonPath); 111 expect(returnInfo[0] === BUNDLE_NAME_DEFAULT).to.be.true; 112 expect(returnInfo[1] === ENTRY_MODULE_NAME_DEFAULT).to.be.true; 113 }); 114 115 mocha.it('2-3: test getPackageInfo under preview debug', function () { 116 this.rollup.preview(); 117 const returnInfo = getPackageInfo(this.rollup.share.projectConfig.aceModuleJsonPath); 118 expect(returnInfo[0] === BUNDLE_NAME_DEFAULT).to.be.true; 119 expect(returnInfo[1] === ENTRY_MODULE_NAME_DEFAULT).to.be.true; 120 }); 121 122 mocha.it('2-4: test getPackageInfo under hot reload debug', function () { 123 this.rollup.hotReload(); 124 const returnInfo = getPackageInfo(this.rollup.share.projectConfig.aceModuleJsonPath); 125 expect(returnInfo[0] === BUNDLE_NAME_DEFAULT).to.be.true; 126 expect(returnInfo[1] === ENTRY_MODULE_NAME_DEFAULT).to.be.true; 127 }); 128 129 mocha.it('3-1: test genSourceMapFileName under build debug', function () { 130 this.rollup.build(); 131 for (const filePath of this.rollup.share.allFiles) { 132 if (filePath.endsWith(EXTNAME_TS) || filePath.endsWith(EXTNAME_JS)) { 133 const originPath = genSourceMapFileName(filePath); 134 const expectedPath = `${filePath}${EXTNAME_MAP}`; 135 expect(originPath === expectedPath).to.be.true; 136 } else if (filePath.endsWith(EXTNAME_ETS)) { 137 const originPath = genSourceMapFileName(filePath); 138 expect(originPath === filePath).to.be.true; 139 } 140 } 141 }); 142 143 mocha.it('3-2: test genSourceMapFileName under build release', function () { 144 this.rollup.build(RELEASE); 145 for (const filePath of this.rollup.share.allFiles) { 146 if (filePath.endsWith(EXTNAME_TS) || filePath.endsWith(EXTNAME_JS)) { 147 const originPath = genSourceMapFileName(filePath); 148 const expectedPath = `${filePath}${EXTNAME_MAP}`; 149 expect(originPath === expectedPath).to.be.true; 150 } 151 } 152 }); 153 154 mocha.it('3-3: test genSourceMapFileName under preview debug', function () { 155 this.rollup.preview(); 156 for (const filePath of this.rollup.share.allFiles) { 157 if (filePath.endsWith(EXTNAME_TS) || filePath.endsWith(EXTNAME_JS)) { 158 const originPath = genSourceMapFileName(filePath); 159 const expectedPath = `${filePath}${EXTNAME_MAP}`; 160 expect(originPath === expectedPath).to.be.true; 161 } 162 } 163 }); 164 165 mocha.it('3-4: test genSourceMapFileName under hot reload debug', function () { 166 this.rollup.hotReload(); 167 for (const filePath of this.rollup.share.allFiles) { 168 if (filePath.endsWith(EXTNAME_TS) || filePath.endsWith(EXTNAME_JS)) { 169 const originPath = genSourceMapFileName(filePath); 170 const expectedPath = `${filePath}${EXTNAME_MAP}`; 171 expect(originPath === expectedPath).to.be.true; 172 } 173 } 174 }); 175 176 mocha.it('4-1: test isOhModules under build debug', function () { 177 this.rollup.build(); 178 const returnInfo = isOhModules(this.rollup.share.projectConfig); 179 expect(returnInfo === false).to.be.true; 180 this.rollup.share.projectConfig.packageDir = OH_MODULES; 181 const returnInfoOh = isOhModules(this.rollup.share.projectConfig); 182 expect(returnInfoOh).to.be.true; 183 }); 184 185 mocha.it('4-2: test isOhModules under build release', function () { 186 this.rollup.build(RELEASE); 187 const returnInfo = isOhModules(this.rollup.share.projectConfig); 188 expect(returnInfo === false).to.be.true; 189 this.rollup.share.projectConfig.packageDir = OH_MODULES; 190 const returnInfoOh = isOhModules(this.rollup.share.projectConfig); 191 expect(returnInfoOh).to.be.true; 192 }); 193 194 mocha.it('4-3: test isOhModules under preview debug', function () { 195 this.rollup.preview(); 196 const returnInfo = isOhModules(this.rollup.share.projectConfig); 197 expect(returnInfo === false).to.be.true; 198 this.rollup.share.projectConfig.packageDir = OH_MODULES; 199 const returnInfoOh = isOhModules(this.rollup.share.projectConfig); 200 expect(returnInfoOh).to.be.true; 201 }); 202 203 mocha.it('4-4: test isOhModules under hot reload debug', function () { 204 this.rollup.hotReload(); 205 const returnInfo = isOhModules(this.rollup.share.projectConfig); 206 expect(returnInfo === false).to.be.true; 207 this.rollup.share.projectConfig.packageDir = OH_MODULES; 208 const returnInfoOh = isOhModules(this.rollup.share.projectConfig); 209 expect(returnInfoOh).to.be.true; 210 }); 211 212 mocha.it('4-5: test isOhModules under hot fix debug', function () { 213 projectConfig.buildMode = DEBUG; 214 const returnInfo = isOhModules(projectConfig); 215 expect(returnInfo).to.be.true; 216 }); 217 218 mocha.it('4-6: test isOhModules under hot fix release', function () { 219 projectConfig.buildMode = RELEASE; 220 const returnInfo = isOhModules(projectConfig); 221 expect(returnInfo).to.be.true; 222 }); 223 224 mocha.it('5-1: test isEs2Abc under build debug', function () { 225 this.rollup.build(); 226 this.rollup.share.projectConfig.pandaMode = ES2ABC; 227 const returnInfo = isEs2Abc(this.rollup.share.projectConfig); 228 expect(returnInfo).to.be.true; 229 230 this.rollup.share.projectConfig.pandaMode = TS2ABC; 231 const returnInfoTS2ABC = isEs2Abc(this.rollup.share.projectConfig); 232 expect(returnInfoTS2ABC === false).to.be.true; 233 234 this.rollup.share.projectConfig.pandaMode = "undefined"; 235 const returnInfoUndef = isEs2Abc(this.rollup.share.projectConfig); 236 expect(returnInfoUndef).to.be.true; 237 238 this.rollup.share.projectConfig.pandaMode = undefined; 239 const returnInfoUndefined = isEs2Abc(this.rollup.share.projectConfig); 240 expect(returnInfoUndefined).to.be.true; 241 }); 242 243 mocha.it('5-2: test isEs2Abc under build release', function () { 244 this.rollup.build(RELEASE); 245 this.rollup.share.projectConfig.pandaMode = ES2ABC; 246 const returnInfo = isEs2Abc(this.rollup.share.projectConfig); 247 expect(returnInfo).to.be.true; 248 249 this.rollup.share.projectConfig.pandaMode = TS2ABC; 250 const returnInfoTS2ABC = isEs2Abc(this.rollup.share.projectConfig); 251 expect(returnInfoTS2ABC).to.be.false; 252 }); 253 254 mocha.it('5-3: test isEs2Abc under preview debug', function () { 255 this.rollup.preview(); 256 this.rollup.share.projectConfig.pandaMode = ES2ABC; 257 const returnInfo = isEs2Abc(this.rollup.share.projectConfig); 258 expect(returnInfo).to.be.true; 259 260 this.rollup.share.projectConfig.pandaMode = TS2ABC; 261 const returnInfoTS2ABC = isEs2Abc(this.rollup.share.projectConfig); 262 expect(returnInfoTS2ABC).to.be.false; 263 }); 264 265 mocha.it('5-4: test isEs2Abc under hot reload debug', function () { 266 this.rollup.hotReload(); 267 this.rollup.share.projectConfig.pandaMode = ES2ABC; 268 const returnInfo = isEs2Abc(this.rollup.share.projectConfig); 269 expect(returnInfo).to.be.true; 270 271 this.rollup.share.projectConfig.pandaMode = TS2ABC; 272 const returnInfoTS2ABC = isEs2Abc(this.rollup.share.projectConfig); 273 expect(returnInfoTS2ABC).to.be.false; 274 }); 275 276 mocha.it('5-5: test isEs2Abc under hot fix debug', function () { 277 projectConfig.buildMode = DEBUG; 278 projectConfig.pandaMode = ES2ABC; 279 const returnInfo = isEs2Abc(projectConfig); 280 expect(returnInfo).to.be.true; 281 282 projectConfig.pandaMode = TS2ABC; 283 const returnInfoTS2ABC = isEs2Abc(projectConfig); 284 expect(returnInfoTS2ABC).to.be.false; 285 }); 286 287 mocha.it('5-6: test isEs2Abc under hot fix release', function () { 288 projectConfig.buildMode = RELEASE; 289 projectConfig.pandaMode = ES2ABC; 290 const returnInfo = isEs2Abc(projectConfig); 291 expect(returnInfo).to.be.true; 292 293 projectConfig.pandaMode = TS2ABC; 294 const returnInfoTS2ABC = isEs2Abc(projectConfig); 295 expect(returnInfoTS2ABC).to.be.false; 296 }); 297 298 mocha.it('6-1: test writeTerserObfuscatedSourceCode under build release', async function () { 299 this.rollup.build(RELEASE); 300 const mockFileList: object = this.rollup.getModuleIds(); 301 for (const moduleId of mockFileList) { 302 if (moduleId.endsWith(EXTNAME_TS)) { 303 const code: string = 304 fs.readFileSync(`${this.rollup.share.projectConfig.projectTopDir}/${ENTRYABILITY_JS}`, 'utf-8'); 305 const moduleSource = new ModuleSourceFileMock(moduleId, code); 306 moduleSource.initPluginEnvMock(this.rollup); 307 const filePath = 308 genTemporaryPath(moduleSource.moduleId, moduleSource.projectConfig.projectPath, 309 moduleSource.projectConfig.cachePath, moduleSource.projectConfig); 310 const newFilePath = changeFileExtension(filePath, EXTNAME_JS); 311 const relativeSourceFilePath: string = 312 toUnixPath(moduleSource.moduleId).replace(toUnixPath(moduleSource.projectConfig.projectRootPath) + '/', ''); 313 const logger: object = this.rollup.share.getLogger(OBFUSCATION_TOOL); 314 const obConfig: ObConfigResolver = new ObConfigResolver(this.rollup.share.projectConfig, logger, true); 315 const mergedObConfig: MergedConfig = obConfig.resolveObfuscationConfigs(); 316 const isHarCompiled: boolean = this.rollup.share.projectConfig.compileHar; 317 moduleSource.projectConfig.terserConfig = 318 utProcessArkConfig.initTerserConfig(this.rollup.share.projectConfig, logger, mergedObConfig, isHarCompiled); 319 const Code: string = fs.readFileSync(moduleId, 'utf-8'); 320 const ModuleSource = new ModuleSourceFile(relativeSourceFilePath, Code); 321 const codeString: MagicString = new MagicString(<string>ModuleSource.source); 322 const sourceMap: object = codeString.generateMap({ 323 source: relativeSourceFilePath, 324 file: `${path.basename(ModuleSource.moduleId)}`, 325 includeContent: false, 326 hires: true 327 }); 328 newSourceMaps[relativeSourceFilePath] = sourceMap; 329 delete newSourceMaps[relativeSourceFilePath].sourcesContent; 330 331 await writeTerserObfuscatedSourceCode(moduleSource.source, newFilePath, moduleSource.logger, 332 moduleSource.projectConfig.terserConfig, relativeSourceFilePath, newSourceMaps); 333 const readFilecontent = fs.readFileSync(newFilePath, 'utf-8'); 334 const expectResult = fs.readFileSync(TERSER_PROCESSED_EXPECTED_CODE, 'utf-8'); 335 expect(readFilecontent === expectResult).to.be.true; 336 } 337 } 338 339 for (const key of Object.keys(newSourceMaps)) { 340 delete newSourceMaps[key]; 341 } 342 }); 343});