1/* 2 * Copyright (c) 2025 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 * as path from 'node:path'; 17import type { CommandLineOptions } from '../lib/CommandLineOptions'; 18import type { LinterOptions } from '../lib/LinterOptions'; 19import { LintTest } from './LintTest'; 20import type { RunTestFileOptions } from './RunTestFileOptions'; 21import { parseCommandLine } from '../cli/CommandLineParser'; 22import { getCommandLineArguments } from './CommandLineUtil'; 23import type { TestModeProperties } from './TestMode'; 24import { DEFAULT_MODE_PROPERTIES, TestMode, testModePropsMap } from './TestMode'; 25import type { TestArguments } from './TestArgs'; 26import { readTestArgsFile } from './TestArgs'; 27import { MigrateTest } from './MigrateTest'; 28 29interface CreateTestOptions { 30 runTestFileOpts: RunTestFileOptions; 31 testModeProps: TestModeProperties; 32 testModeArgs?: string; 33 testCommonOpts?: LinterOptions; 34} 35 36export interface CreateLintTestOptions { 37 testDir: string; 38 testFile: string; 39 testModeProps: TestModeProperties; 40 cmdOptions: CommandLineOptions; 41} 42 43export function createTests(runTestFileOpts: RunTestFileOptions): LintTest[] { 44 const testArgs = readTestArgsFile(runTestFileOpts.testDir, runTestFileOpts.testFile); 45 return testArgs ? 46 createTestsFromTestArgs(runTestFileOpts, testArgs) : 47 [createTest({ runTestFileOpts, testModeProps: DEFAULT_MODE_PROPERTIES })]; 48} 49 50function createTestsFromTestArgs(runTestFileOpts: RunTestFileOptions, testArgs: TestArguments): LintTest[] { 51 const tests: LintTest[] = []; 52 const testCommonOpts = testArgs.commonArgs ? getLinterOptionsFromCommandLine(testArgs.commonArgs) : undefined; 53 54 addDefaultModeIfNeeded(testArgs); 55 56 if (testArgs.mode) { 57 for (const mode of Object.keys(testArgs.mode)) { 58 const testModeProps = testModePropsMap.get(mode); 59 if (!testModeProps) { 60 throw new Error(`Failed to create test. Unknown mode: '${mode}'`); 61 } 62 const testModeArgs: string | undefined = testArgs.mode[mode]; 63 tests.push(createTest({ runTestFileOpts, testModeProps, testCommonOpts, testModeArgs })); 64 } 65 } 66 67 return tests; 68} 69 70function addDefaultModeIfNeeded(testArgs: TestArguments): void { 71 if (testArgs.mode?.default === undefined) { 72 // For convenience, always add 'default' mode as first 73 testArgs.mode = Object.assign({ default: '' }, testArgs.mode); 74 } 75} 76 77function createTest(createTestOpts: CreateTestOptions): LintTest { 78 const opts = createCreateLintTestOpts(createTestOpts); 79 if (createTestOpts.testModeProps.mode === TestMode.MIGRATE) { 80 return new MigrateTest(opts); 81 } 82 return new LintTest(opts); 83} 84 85function createCreateLintTestOpts(createTestConfigOpts: CreateTestOptions): CreateLintTestOptions { 86 const { runTestFileOpts, testCommonOpts, testModeArgs, testModeProps } = createTestConfigOpts; 87 const { testDir, testFile, testRunnerOpts } = runTestFileOpts; 88 89 /* 90 * Test options are formed in the following order (from lowest to highest priority): 91 * - default test options; 92 * - [test_args_file] --> 'commonArgs'; 93 * - [test_args_file] --> the arguments specified for a mode; 94 * - options specified by TestRunner command-line arguments; 95 * - options that enable specific mode. 96 */ 97 const linterOpts = getDefaultTestOptions(); 98 if (testCommonOpts) { 99 Object.assign(linterOpts, testCommonOpts); 100 } 101 if (testModeArgs) { 102 Object.assign(linterOpts, getLinterOptionsFromCommandLine(testModeArgs)); 103 } 104 Object.assign(linterOpts, testRunnerOpts.linterOptions); 105 Object.assign(linterOpts, testModeProps.modeOpts); 106 107 const cmdOptions: CommandLineOptions = { 108 inputFiles: [path.join(testDir, testFile)], 109 linterOptions: linterOpts 110 }; 111 112 return { 113 testDir, 114 testFile, 115 testModeProps, 116 cmdOptions 117 }; 118} 119 120function getLinterOptionsFromCommandLine(cmdLine: string): LinterOptions { 121 return parseCommandLine(getCommandLineArguments(cmdLine), { exitOnFail: false, disableErrorOutput: true }). 122 linterOptions; 123} 124 125function getDefaultTestOptions(): LinterOptions { 126 return { 127 useRtLogic: true, 128 checkTsAsSource: 129 true /* By default, treat any test file with '.ts' extension as a source file (as opposed to library) */, 130 compatibleSdkVersion: 12, 131 compatibleSdkVersionStage: 'beta3', 132 checkTsAndJs: true 133 }; 134} 135