From 9fd9cbf46ef2ac2c8e5c08ee8f3f87a9fa512dd1 Mon Sep 17 00:00:00 2001 From: kleene Date: Sun, 17 Aug 2025 17:06:04 +0800 Subject: [PATCH] fix koalaModule is undefined Issue: ICTBZ4 Signed-off-by: kleene Change-Id: Ia13d225609e5996f573b821698b5081ceeebe5eb --- .../build_system/src/build/base_mode.ts | 7 +- ets2panda/driver/build_system/src/entry.ts | 2 + .../src/init/init_koala_modules.ts | 38 +- .../test/ut/entryTest/entry.test.ts | 340 +++++++----------- .../ut/initTest/init_koala_modules.test.ts | 65 ++++ 5 files changed, 226 insertions(+), 226 deletions(-) create mode 100644 ets2panda/driver/build_system/test/ut/initTest/init_koala_modules.test.ts diff --git a/ets2panda/driver/build_system/src/build/base_mode.ts b/ets2panda/driver/build_system/src/build/base_mode.ts index a52992540b..c3676d24ba 100644 --- a/ets2panda/driver/build_system/src/build/base_mode.ts +++ b/ets2panda/driver/build_system/src/build/base_mode.ts @@ -84,6 +84,7 @@ import { } from '../utils/record_time_mem'; import { TaskManager } from '../util/TaskManager'; import { handleCompileWorkerExit } from '../util/worker_exit_handler'; +import { initKoalaModules } from '../init/init_koala_modules'; export abstract class BaseMode { public buildConfig: BuildConfig; @@ -266,8 +267,7 @@ export abstract class BaseMode { ets2pandaCmd.push(fileInfo.filePath); this.logger.printInfo('ets2pandaCmd: ' + ets2pandaCmd.join(' ')); - const arktsGlobal = this.buildConfig.arktsGlobal; - const arkts = this.buildConfig.arkts; + let { arkts, arktsGlobal } = initKoalaModules(this.buildConfig) let errorStatus = false; try { arktsGlobal.filePath = fileInfo.filePath; @@ -364,8 +364,7 @@ export abstract class BaseMode { ets2pandaCmd.push(this.buildConfig.compileFiles[0]); this.logger.printInfo('ets2pandaCmd: ' + ets2pandaCmd.join(' ')); - let arktsGlobal = this.buildConfig.arktsGlobal; - let arkts = this.buildConfig.arkts; + let { arkts, arktsGlobal } = initKoalaModules(this.buildConfig); let errorStatus = false; try { arktsGlobal.config = arkts.Config.create(ets2pandaCmd).peer; diff --git a/ets2panda/driver/build_system/src/entry.ts b/ets2panda/driver/build_system/src/entry.ts index c20fe57e7a..b590749038 100644 --- a/ets2panda/driver/build_system/src/entry.ts +++ b/ets2panda/driver/build_system/src/entry.ts @@ -23,6 +23,7 @@ import { ArkTSConfigGenerator } from './build/generate_arktsconfig'; import { PluginDriver } from './plugins/plugins_driver'; import { BuildConfig, BUILD_TYPE } from './types'; import { BuildFrameworkMode } from './build/build_framework_mode'; +import { cleanKoalaModule } from './init/init_koala_modules'; export async function build(projectConfig: BuildConfig): Promise { let logger: Logger = Logger.getInstance(projectConfig); @@ -51,6 +52,7 @@ function clean(): void { Logger.destroyInstance(); ArkTSConfigGenerator.destroyInstance(); PluginDriver.destroyInstance(); + cleanKoalaModule(); } function main(): void { diff --git a/ets2panda/driver/build_system/src/init/init_koala_modules.ts b/ets2panda/driver/build_system/src/init/init_koala_modules.ts index f24b5eba64..9c3808f3d1 100644 --- a/ets2panda/driver/build_system/src/init/init_koala_modules.ts +++ b/ets2panda/driver/build_system/src/init/init_koala_modules.ts @@ -22,20 +22,27 @@ import path from "path" let koalaModule: any; export function initKoalaModules(buildConfig: BuildConfig) { - if (koalaModule) return koalaModule - - const koalaWrapperPath = process.env.KOALA_WRAPPER_PATH ?? path.resolve(buildConfig.buildSdkPath, KOALA_WRAPPER_PATH_FROM_SDK); - koalaModule = require(koalaWrapperPath); - koalaModule.arktsGlobal.es2panda._SetUpSoPath(buildConfig.pandaSdkPath); - buildConfig.arkts = koalaModule.arkts; - buildConfig.arktsGlobal = koalaModule.arktsGlobal; - return koalaModule + if (!koalaModule) { + const koalaWrapperPath = + process.env.KOALA_WRAPPER_PATH ?? + path.resolve(buildConfig.buildSdkPath, KOALA_WRAPPER_PATH_FROM_SDK); + + koalaModule = require(koalaWrapperPath); + koalaModule.arktsGlobal.es2panda._SetUpSoPath(buildConfig.pandaSdkPath); + } + + Object.assign(buildConfig, { + arkts: koalaModule.arkts, + arktsGlobal: koalaModule.arktsGlobal, + }); + + return koalaModule; } -export function initKoalaPlugins(projectConfig: BuildConfig): void { - const uiPluginPath = path.resolve(projectConfig.buildSdkPath, UI_PLUGIN_PATH_FROM_SDK); - const memoPluginPath = path.resolve(projectConfig.buildSdkPath, MEMO_PLUGIN_PATH_FROM_SDK); +export function initKoalaPlugins(projectConfig: BuildConfig): void { + const uiPluginPath = path.resolve(projectConfig.buildSdkPath, UI_PLUGIN_PATH_FROM_SDK); + const memoPluginPath = path.resolve(projectConfig.buildSdkPath, MEMO_PLUGIN_PATH_FROM_SDK); // TODO: need change in hvigor if (process.env.USE_KOALA_UI_PLUGIN) { @@ -45,4 +52,13 @@ export function initKoalaPlugins(projectConfig: BuildConfig): void { if (process.env.USE_KOALA_MEMO_PLUGIN) { projectConfig.plugins['ArkUI-Memo'] = memoPluginPath } +} + +export function cleanKoalaModule() { + koalaModule = null; +} + +// for ut +export function getKoalaModule() { + return koalaModule; } \ No newline at end of file diff --git a/ets2panda/driver/build_system/test/ut/entryTest/entry.test.ts b/ets2panda/driver/build_system/test/ut/entryTest/entry.test.ts index 060d717957..c59341873c 100755 --- a/ets2panda/driver/build_system/test/ut/entryTest/entry.test.ts +++ b/ets2panda/driver/build_system/test/ut/entryTest/entry.test.ts @@ -14,8 +14,17 @@ */ import * as entryModule from '../../../src/entry'; -import { BUILD_TYPE, BuildConfig, OHOS_MODULE_TYPE, BUILD_MODE } from '../../../src/types'; +import { + BUILD_TYPE, + BuildConfig, + OHOS_MODULE_TYPE, + BUILD_MODE +} from '../../../src/types'; import { Logger } from '../../../src/logger'; +import { + getKoalaModule, + cleanKoalaModule +} from '../../../src/init/init_koala_modules'; jest.mock('../../../src/build/build_mode'); jest.mock('../../../src/build/build_framework_mode'); @@ -27,224 +36,133 @@ jest.mock('../../../src/init/process_build_config', () => ({ beforeEach(() => { jest.clearAllMocks(); process.exit = jest.fn() as any; + cleanKoalaModule(); }); -function testBuildTypeBranch() { - const BuildMode = require('../../../src/build/build_mode').BuildMode; - const BuildFrameworkMode = require('../../../src/build/build_framework_mode').BuildFrameworkMode; - const mockBuildModeRun = jest.fn().mockResolvedValue(undefined); - BuildMode.mockImplementation(() => { - return { - run: mockBuildModeRun, +describe('entry.ts build function with clean', () => { + function setupLogger(hasErrors = false) { + Logger.getInstance = jest.fn().mockReturnValue({ + hasErrors: jest.fn().mockReturnValue(hasErrors), + printInfo: jest.fn(), + printError: jest.fn() + }); + } + + test('BUILD_TYPE.BUILD branch cleans and calls BuildMode', async () => { + const BuildMode = require('../../../src/build/build_mode').BuildMode; + const mockRun = jest.fn().mockResolvedValue(undefined); + BuildMode.mockImplementation((config: BuildConfig) => ({ + run: mockRun, generateDeclaration: jest.fn() - }; + })); + setupLogger(); + + const mockConfig = { + buildType: BUILD_TYPE.BUILD, + packageName: 'test', + compileFiles: ['test.ets'], + enableDeclgenEts2Ts: false, + frameworkMode: false, + loaderOutPath: './dist', + cachePath: './dist/cache', + moduleType: OHOS_MODULE_TYPE.HAR, + sourceRoots: ['./'], + moduleRootPath: '/test/path', + buildMode: BUILD_MODE.DEBUG + } as BuildConfig; + + await entryModule.build(mockConfig); + + expect(BuildMode).toHaveBeenCalledWith(expect.objectContaining({ + buildType: BUILD_TYPE.BUILD, + packageName: 'test' + })); + expect(mockRun).toHaveBeenCalled(); + expect(getKoalaModule()).toBeNull(); }); - const mockLoggerHasErrors = jest.fn().mockReturnValue(false); - Logger.getInstance = jest.fn().mockReturnValue({ - hasErrors: mockLoggerHasErrors, - printInfo: jest.fn(), - printError: jest.fn() + test('frameworkMode branch cleans and calls BuildFrameworkMode', async () => { + const BuildFrameworkMode = require('../../../src/build/build_framework_mode').BuildFrameworkMode; + const mockRun = jest.fn().mockResolvedValue(undefined); + BuildFrameworkMode.mockImplementation(() => ({ run: mockRun })); + + setupLogger(); + + const mockConfig = { + buildType: BUILD_TYPE.BUILD, + packageName: 'test', + compileFiles: ['test.ets'], + enableDeclgenEts2Ts: false, + frameworkMode: true, + loaderOutPath: './dist', + cachePath: './dist/cache', + moduleType: OHOS_MODULE_TYPE.HAR, + sourceRoots: ['./'], + moduleRootPath: '/test/path', + buildMode: BUILD_MODE.DEBUG + } as BuildConfig; + + await entryModule.build(mockConfig); + + expect(BuildFrameworkMode).toHaveBeenCalledWith(expect.objectContaining({ + frameworkMode: true, + packageName: 'test' + })); + expect(mockRun).toHaveBeenCalled(); + expect(getKoalaModule()).toBeNull(); }); - const mockConfig = { - buildType: BUILD_TYPE.BUILD, - packageName: 'test', - compileFiles: ['test.ets'], - enableDeclgenEts2Ts: false, - frameworkMode: false, - loaderOutPath: './dist', - cachePath: './dist/cache', - moduleType: OHOS_MODULE_TYPE.HAR, - sourceRoots: ['./'], - moduleRootPath: '/test/path', - buildMode: BUILD_MODE.DEBUG - } as BuildConfig; - return { - buildMode: BuildMode, - frameworkMode: BuildFrameworkMode, - mockBuildModeRun, - mockConfig, - execute: async () => { - await entryModule.build(mockConfig); - expect(BuildMode).toHaveBeenCalledWith(expect.objectContaining({ - buildType: BUILD_TYPE.BUILD, - entryFiles: mockConfig.compileFiles - })); - expect(mockBuildModeRun).toHaveBeenCalled(); - expect(BuildFrameworkMode).not.toHaveBeenCalled(); - } - }; -} - -function testFrameworkModeBranch() { - const BuildMode = require('../../../src/build/build_mode').BuildMode; - const BuildFrameworkMode = require('../../../src/build/build_framework_mode').BuildFrameworkMode; - - const mockFrameworkModeRun = jest.fn().mockResolvedValue(undefined); - BuildFrameworkMode.mockImplementation(() => { - return { - run: mockFrameworkModeRun - }; + test('enableDeclgenEts2Ts branch cleans and calls generateDeclaration', async () => { + const BuildMode = require('../../../src/build/build_mode').BuildMode; + const mockGenerateDeclaration = jest.fn().mockResolvedValue(undefined); + BuildMode.mockImplementation(() => ({ run: jest.fn(), generateDeclaration: mockGenerateDeclaration })); + + setupLogger(); + + const mockConfig = { + buildType: BUILD_TYPE.BUILD, + packageName: 'test', + compileFiles: ['test.ets'], + enableDeclgenEts2Ts: true, + frameworkMode: false, + loaderOutPath: './dist', + cachePath: './dist/cache', + moduleType: OHOS_MODULE_TYPE.HAR, + sourceRoots: ['./'], + moduleRootPath: '/test/path', + buildMode: BUILD_MODE.DEBUG + } as BuildConfig; + + await entryModule.build(mockConfig); + + expect(BuildMode).toHaveBeenCalledWith(expect.objectContaining({ + enableDeclgenEts2Ts: true, + packageName: 'test' + })); + expect(mockGenerateDeclaration).toHaveBeenCalled(); + expect(getKoalaModule()).toBeNull(); }); - const mockLoggerHasErrors = jest.fn().mockReturnValue(false); - Logger.getInstance = jest.fn().mockReturnValue({ - hasErrors: mockLoggerHasErrors, - printInfo: jest.fn(), - printError: jest.fn() - }); - - const mockConfig = { - buildType: BUILD_TYPE.BUILD, - packageName: 'test', - compileFiles: ['test.ets'], - enableDeclgenEts2Ts: false, - frameworkMode: true, - loaderOutPath: './dist', - cachePath: './dist/cache', - moduleType: OHOS_MODULE_TYPE.HAR, - sourceRoots: ['./'], - moduleRootPath: '/test/path', - buildMode: BUILD_MODE.DEBUG - } as BuildConfig; - - return { - buildMode: BuildMode, - frameworkMode: BuildFrameworkMode, - mockFrameworkModeRun, - mockConfig, - mockLoggerHasErrors, - execute: async () => { - await entryModule.build(mockConfig); - expect(BuildFrameworkMode).toHaveBeenCalledWith(expect.objectContaining({ - frameworkMode: true, - entryFiles: mockConfig.compileFiles - })); - expect(mockFrameworkModeRun).toHaveBeenCalled(); - expect(BuildMode).not.toHaveBeenCalled(); - expect(process.exit).not.toHaveBeenCalled(); - } - }; -} - -function testEnableDeclgenEts2TsBranch() { - const BuildMode = require('../../../src/build/build_mode').BuildMode; - const BuildFrameworkMode = require('../../../src/build/build_framework_mode').BuildFrameworkMode; - const mockGenerateDeclaration = jest.fn().mockResolvedValue(undefined); - BuildMode.mockImplementation(() => { - return { - run: jest.fn(), - generateDeclaration: mockGenerateDeclaration - }; - }); - - Logger.getInstance = jest.fn().mockReturnValue({ - hasErrors: jest.fn().mockReturnValue(false), - printInfo: jest.fn(), - printError: jest.fn() - }); - - const mockConfig = { - buildType: BUILD_TYPE.BUILD, - packageName: 'test', - compileFiles: ['test.ets'], - enableDeclgenEts2Ts: true, - frameworkMode: false, - loaderOutPath: './dist', - cachePath: './dist/cache', - moduleType: OHOS_MODULE_TYPE.HAR, - sourceRoots: ['./'], - moduleRootPath: '/test/path', - buildMode: BUILD_MODE.DEBUG - } as BuildConfig; - - return { - buildMode: BuildMode, - frameworkMode: BuildFrameworkMode, - mockGenerateDeclaration, - mockConfig, - execute: async () => { - await entryModule.build(mockConfig); - expect(BuildMode).toHaveBeenCalledWith(expect.objectContaining({ - enableDeclgenEts2Ts: true, - entryFiles: mockConfig.compileFiles - })); - expect(mockGenerateDeclaration).toHaveBeenCalled(); - expect(BuildFrameworkMode).not.toHaveBeenCalled(); - } - }; -} - -function testNoMatchingBranch() { - const BuildMode = require('../../../src/build/build_mode').BuildMode; - const BuildFrameworkMode = require('../../../src/build/build_framework_mode').BuildFrameworkMode; - BuildMode.mockReset(); - BuildFrameworkMode.mockReset(); - const mockBuildModeRun = jest.fn(); - const mockGenerateDeclaration = jest.fn(); - const mockLoggerHasErrors = jest.fn() - .mockReturnValueOnce(true) - .mockReturnValueOnce(false); - Logger.getInstance = jest.fn().mockReturnValue({ - hasErrors: mockLoggerHasErrors, - printInfo: jest.fn(), - printError: jest.fn() - }); - const clean = jest.fn(); - jest.mock('../../../src/entry.ts', () => ({ - clean: clean - })); - const mockConfig = { - buildType: BUILD_TYPE.PREVIEW, - packageName: 'test', - compileFiles: ['test.ets'], - enableDeclgenEts2Ts: false, - frameworkMode: true, - loaderOutPath: './dist', - cachePath: './dist/cache', - moduleType: OHOS_MODULE_TYPE.HAR, - sourceRoots: ['./'], - moduleRootPath: '/test/path', - buildMode: BUILD_MODE.DEBUG - } as BuildConfig; - return { - buildMode: BuildMode, - frameworkMode: BuildFrameworkMode, - mockBuildModeRun, - mockGenerateDeclaration, - mockConfig, - mockLoggerHasErrors, - clean, - execute: async () => { - await entryModule.build(mockConfig); - expect(mockLoggerHasErrors).toHaveBeenCalled(); - jest.clearAllMocks(); - await entryModule.build(mockConfig); - expect(BuildMode).not.toHaveBeenCalled(); - } - }; -} - -// Test the functions of the entry.ts file -describe('test entry.ts file api', () => { - test('test build function BUILD_TYPE.BUILD branch', async () => { - const testCase = testBuildTypeBranch(); - await testCase.execute(); - }); - - test('test build function frameworkMode branch', async () => { - const testCase = testFrameworkModeBranch(); - await testCase.execute(); - }); - - test('test build function enableDeclgenEts2Ts branch', async () => { - const testCase = testEnableDeclgenEts2TsBranch(); - await testCase.execute(); - }); - - test('test build function no matching branch', async () => { - const testCase = testNoMatchingBranch(); - await testCase.execute(); + test('no matching branch cleans and exits on error', async () => { + setupLogger(true); // hasErrors = true + + const mockConfig = { + buildType: BUILD_TYPE.PREVIEW, + packageName: 'test', + compileFiles: ['test.ets'], + enableDeclgenEts2Ts: false, + frameworkMode: true, + loaderOutPath: './dist', + cachePath: './dist/cache', + moduleType: OHOS_MODULE_TYPE.HAR, + sourceRoots: ['./'], + moduleRootPath: '/test/path', + buildMode: BUILD_MODE.DEBUG + } as BuildConfig; + + await entryModule.build(mockConfig); + + expect(process.exit).toHaveBeenCalledWith(1); + expect(getKoalaModule()).toBeNull(); }); }); diff --git a/ets2panda/driver/build_system/test/ut/initTest/init_koala_modules.test.ts b/ets2panda/driver/build_system/test/ut/initTest/init_koala_modules.test.ts new file mode 100644 index 0000000000..71fcde7d13 --- /dev/null +++ b/ets2panda/driver/build_system/test/ut/initTest/init_koala_modules.test.ts @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { initKoalaModules, cleanKoalaModule } from '../../../src/init/init_koala_modules'; +import type { BuildConfig } from '../../../src/types'; + +const fakeKoalaModule = { + arkts: {}, + arktsGlobal: { + es2panda: { _SetUpSoPath: jest.fn() }, + }, +}; + +jest.mock('/mock/build/path/build-tools/koala-wrapper/build/lib/es2panda', () => fakeKoalaModule, { virtual: true }); + +describe('initKoalaModules', () => { + let buildConfig: BuildConfig; + + beforeEach(() => { + buildConfig = { + buildSdkPath: '/mock/build/path', + pandaSdkPath: '/mock/panda/path', + } as any; + + cleanKoalaModule(); + fakeKoalaModule.arktsGlobal.es2panda._SetUpSoPath.mockClear(); + }); + + it('should load koalaModule and inject into buildConfig', () => { + const koala = initKoalaModules(buildConfig); + + expect(koala).toBe(fakeKoalaModule); + expect(buildConfig.arkts).toBe(fakeKoalaModule.arkts); + expect(buildConfig.arktsGlobal).toBe(fakeKoalaModule.arktsGlobal); + expect(fakeKoalaModule.arktsGlobal.es2panda._SetUpSoPath).toHaveBeenCalledWith(buildConfig.pandaSdkPath); + }); + + it('should reuse koalaModule on subsequent calls', () => { + const first = initKoalaModules(buildConfig); + const second = initKoalaModules(buildConfig); + + expect(first).toBe(second); + expect(fakeKoalaModule.arktsGlobal.es2panda._SetUpSoPath).toHaveBeenCalledTimes(1); + }); + + it('should clean koalaModule', () => { + initKoalaModules(buildConfig); + cleanKoalaModule(); + + const koala = initKoalaModules(buildConfig); + expect(koala).toBe(fakeKoalaModule); + }); +}); -- Gitee