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 16import { expect } from 'chai'; 17import mocha from 'mocha'; 18import sinon from 'sinon'; 19import fs from 'fs'; 20import cluster from 'cluster'; 21import path from 'path'; 22 23import RollUpPluginMock from '../mock/rollup_mock/rollup_plugin_mock'; 24import { BundleMode } from '../../../lib/fast_build/ark_compiler/bundle/bundle_mode'; 25import { changeFileExtension } from '../../../lib/fast_build/ark_compiler/utils' 26import { 27 DEBUG, 28 RELEASE, 29 TEMPORARY 30} from '../../../lib/fast_build/ark_compiler/common/ark_define' 31import { toUnixPath } from '../../../lib/utils' 32 33mocha.describe('test bundle_mode file api', function () { 34 mocha.before(function () { 35 this.rollup = new RollUpPluginMock(); 36 }); 37 38 mocha.after(() => { 39 delete this.rollup; 40 }); 41 42 mocha.it('1-1: test error message of executeArkCompiler', function () { 43 this.rollup.build(); 44 const rollupBundleFileSet: Object = { 45 'test.js': { 46 'type': 'asset', 47 'source': 'test' 48 } 49 }; 50 const bundleMode = new BundleMode(this.rollup, rollupBundleFileSet); 51 bundleMode.projectConfig.pandaMode = 'invalid value'; 52 const stub = sinon.stub(bundleMode, 'throwArkTsCompilerError'); 53 bundleMode.executeArkCompiler(); 54 expect(stub.calledWith('ArkTS:INTERNAL ERROR: Invalid compilation mode.')).to.be.true; 55 stub.restore(); 56 }); 57 58 mocha.it('2-1: test the error message of executeEs2AbcCmd handler error', async function () { 59 this.rollup.build(); 60 const rollupBundleFileSet: Object = { 61 'test.js': { 62 'type': 'asset', 63 'source': 'test' 64 } 65 }; 66 const bundleMode = new BundleMode(this.rollup, rollupBundleFileSet); 67 const triggerAsyncStub = sinon.stub(bundleMode, 'triggerAsync').throws(new Error('Execution failed')); 68 const stub = sinon.stub(bundleMode, 'throwArkTsCompilerError'); 69 try { 70 bundleMode.executeEs2AbcCmd(); 71 } catch (e) { 72 } 73 expect(stub.calledWithMatch('ArkTS:ERROR failed to execute es2abc with async handler: ')).to.be.true; 74 triggerAsyncStub.restore(); 75 stub.restore(); 76 }); 77 78 mocha.it('3-1: test the error message of collectBundleFileList(file.type is invalid value)', function () { 79 this.rollup.build(); 80 const rollupBundleFileSet: Object = { 81 'test.js': { 82 'type': '' 83 } 84 }; 85 const stub = sinon.stub(this.rollup.share, 'throwArkTsCompilerError'); 86 new BundleMode(this.rollup, rollupBundleFileSet); 87 expect(stub.calledWith('ArkTS:INTERNAL ERROR: Failed to retrieve source code ' + 88 'for test.js from rollup file set.')).to.be.true; 89 stub.restore(); 90 }); 91 92 mocha.it('3-2: test the error message of collectBundleFileList', function () { 93 this.rollup.build(); 94 const rollupBundleFileSet: Object = { 95 'test.js': { 96 'type': 'asset', 97 'source': 'test' 98 } 99 }; 100 const existsSyncStub = sinon.stub(fs, 'existsSync').callsFake((path) => { 101 const pattern = /test\.temp\.js$/; 102 if (pattern.test(path)) { 103 return false; 104 } 105 return true; 106 }); 107 const stub = sinon.stub(this.rollup.share, 'throwArkTsCompilerError'); 108 try { 109 new BundleMode(this.rollup, rollupBundleFileSet); 110 } catch (e) { 111 } 112 expect(stub.calledWith('ArkTS:INTERNAL ERROR: Failed to generate cached source file: test.js')).to.be.true; 113 existsSyncStub.restore(); 114 stub.restore(); 115 }); 116 117 mocha.it('4-1: test the error message of filterBundleFileListWithHashJson', function () { 118 this.rollup.build(); 119 const rollupBundleFileSet: Object = { 120 'test.js': { 121 'type': 'asset', 122 'source': 'test' 123 } 124 }; 125 const bundleMode = new BundleMode(this.rollup, rollupBundleFileSet); 126 const jsonData = JSON.stringify(rollupBundleFileSet, null, 2); 127 const stub = sinon.stub(bundleMode, 'throwArkTsCompilerError'); 128 for (const value of bundleMode.intermediateJsBundle.values()) { 129 fs.unlinkSync(value.cacheFilePath); 130 } 131 fs.writeFileSync(bundleMode.hashJsonFilePath, jsonData) 132 bundleMode.filterBundleFileListWithHashJson(); 133 expect(stub.calledWithMatch('ArkTS:INTERNAL ERROR: Failed to get bundle cached abc from ')).to.be.true; 134 stub.restore(); 135 }); 136 137 mocha.it('5-1: test the error message of invokeTs2AbcWorkersToGenAbc(worker error)', function () { 138 this.rollup.build(); 139 const rollupBundleFileSet: Object = { 140 'test.js': { 141 'type': 'asset', 142 'source': 'test' 143 } 144 }; 145 const bundleMode = new BundleMode(this.rollup, rollupBundleFileSet); 146 const stub = sinon.stub(bundleMode, 'throwArkTsCompilerError'); 147 const clusterStub = sinon.stub(cluster, 'fork'); 148 const fakeWorker = { 149 on: sinon.stub() 150 }; 151 clusterStub.returns(fakeWorker); 152 const splittedBundles = bundleMode.getSplittedBundles() 153 try { 154 fakeWorker.on.withArgs('message').callsFake((event, callback) => { 155 callback({ data: 'error' }); 156 }); 157 bundleMode.invokeTs2AbcWorkersToGenAbc(splittedBundles) 158 } catch (e) { 159 } 160 expect(stub.calledWith('ArkTS:ERROR Failed to execute ts2abc')).to.be.true; 161 clusterStub.restore(); 162 stub.restore(); 163 }); 164 165 mocha.it('6-1: test the error message of writeHashJson', function () { 166 this.rollup.build(); 167 const rollupBundleFileSet: Object = { 168 'test.js': { 169 'type': 'asset', 170 'source': 'test' 171 } 172 }; 173 const bundleMode = new BundleMode(this.rollup, rollupBundleFileSet); 174 const stub = sinon.stub(bundleMode, 'throwArkTsCompilerError'); 175 try { 176 bundleMode.writeHashJson(); 177 } catch (e) { 178 } 179 expect(stub.calledWithMatch('ArkTS:INTERNAL ERROR: During hash JSON file generation, ')).to.be.true; 180 stub.restore(); 181 }); 182 183 mocha.it('7-1: test the error message of copyFileFromCachePathToOutputPath', function () { 184 this.rollup.build(); 185 const rollupBundleFileSet: Object = { 186 'test.js': { 187 'type': 'asset', 188 'source': 'test' 189 } 190 }; 191 const bundleMode = new BundleMode(this.rollup, rollupBundleFileSet); 192 const stub = sinon.stub(bundleMode, 'throwArkTsCompilerError'); 193 try { 194 bundleMode.copyFileFromCachePathToOutputPath(); 195 } catch (e) { 196 } 197 expect(stub.calledWithMatch('not found during incremental build. ' + 198 'Please try to rebuild the project')).to.be.true; 199 stub.restore(); 200 }); 201 202 mocha.it('8-1: test sourceFile field of bundle mode in release', function () { 203 this.rollup.build(); 204 this.rollup.share.projectConfig.buildMode = RELEASE 205 const rollupBundleFileSet: Object = { 206 'test.js': { 207 'type': 'asset', 208 'source': 'test' 209 } 210 }; 211 const bundleMode = new BundleMode(this.rollup, rollupBundleFileSet); 212 const filesinfo: string[] = fs.readFileSync(bundleMode.generateFileInfoOfBundle()).toString().split(";"); 213 // sourceFile is the 4th field in filesInfo 214 const sourceFile: string = filesinfo[3]; 215 const relativeCachePath: string = toUnixPath(bundleMode.projectConfig.cachePath.replace( 216 bundleMode.projectConfig.projectRootPath + path.sep, '')); 217 const buildDirArr: string[] = bundleMode.projectConfig.aceModuleBuild.split(path.sep); 218 const abilityDir: string = buildDirArr[buildDirArr.length - 1]; 219 220 expect(sourceFile === path.join(relativeCachePath, TEMPORARY, abilityDir, 'test.temp.js')).to.be.true; 221 }); 222 223 mocha.it('9-1: test sourceFile field of bundle mode in debug', function () { 224 this.rollup.build(); 225 this.rollup.share.projectConfig.buildMode = DEBUG 226 const rollupBundleFileSet: Object = { 227 'test.js': { 228 'type': 'asset', 229 'source': 'test' 230 } 231 }; 232 const bundleMode = new BundleMode(this.rollup, rollupBundleFileSet); 233 const filesinfo: string[] = fs.readFileSync(bundleMode.generateFileInfoOfBundle()).toString().split(";"); 234 // sourceFile is the 4th field in filesInfo 235 const sourceFile: string = filesinfo[3]; 236 const relativePath: string = toUnixPath(bundleMode.projectConfig.aceModuleBuild.replace( 237 bundleMode.projectConfig.projectRootPath + path.sep, '')); 238 239 expect(sourceFile === path.join(relativePath, 'test.js')).to.be.true; 240 }); 241});