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 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 16 17const ts = require('typescript'); 18const path = require('path'); 19const fs = require('fs') 20 21 22const ignoreCaseFilePath= path.join(__dirname, "ignorecase.json") 23const compResults = {"detail":{}, 'failNum':0, "passedNum":0} 24let consoleDetail = false; ignoreList = []; failTestCaseList = []; genResultFile = false 25// Traverse the directory to find all test cases 26function getAllETSFiles(filePath) { 27 let allFilePaths = []; 28 if (fs.existsSync(filePath)) { 29 const files = fs.readdirSync(filePath); 30 for (let i = 0; i < files.length; i++) { 31 let file = files[i]; // File name (excluding file path) 32 let currentFilePath = filePath + '/' + file; 33 let stats = fs.lstatSync(currentFilePath); 34 if(ignoreList.includes(currentFilePath)){ 35 continue 36 } 37 if (stats.isDirectory()) { 38 allFilePaths = allFilePaths.concat(getAllETSFiles(currentFilePath)); 39 } else { 40 var index= currentFilePath.lastIndexOf("."); 41 var ext = currentFilePath.substring(index+1); 42 if (ext == "ets"){ 43 allFilePaths.push(currentFilePath); 44 runComp(currentFilePath, file) 45 } 46 } 47 } 48 } else { 49 console.warn(`The specified directory ${filePath} Non-existent!`); 50 } 51 return allFilePaths; 52} 53 54function runComp(currentFilePath, file){ 55 const result = runLinter(currentFilePath) 56 const jsonFile = currentFilePath.replace('ets','json') 57 const checkfile = fs.existsSync(jsonFile); 58 if(checkfile){ 59 loadPares(jsonFile, result, currentFilePath, file) 60 }else{ 61 if(!currentFilePath.includes("-dependencie.ets")){ 62 console.log(`Test cases ${currentFilePath} expected results are not added`) 63 } 64 } 65} 66 67// Compare the results with expectations and count the success and failure situations 68function loadPares(jsonFile, result, currentFilePath, file){ 69 const dirName = path.dirname(currentFilePath) 70 let rules = "" 71 if (dirName.includes("\\")){ 72 rules = currentFilePath.split("\\")[currentFilePath.split("\\").length - 2] 73 }else{ 74 rules = currentFilePath.split("/")[currentFilePath.split("/").length - 2] 75 } 76 const testCaseFileName = file 77 dataStr = fs.readFileSync(jsonFile, "utf-8") 78 const expect = JSON.parse(dataStr) 79 const compResult = compareResult(expect, result) 80 compResult["testCaseName"] = testCaseFileName 81 if (compResults["detail"].hasOwnProperty(rules)){ 82 compResults["detail"][rules]["detail"].push(compResult) 83 compResults["detail"][rules]["testCaseNum"] += 1 84 }else{ 85 compResults["detail"][rules] = {"detail":[compResult], "testCaseNum": 1, "failNum": 0, "passedNum": 0} 86 } 87 if(compResult.status){ 88 compResults["passedNum"] += 1 89 compResults["detail"][rules]["passedNum"] += 1 90 }else{ 91 failTestCaseList.push(currentFilePath) 92 if(consoleDetail){ 93 console.log(`Test cases ${currentFilePath} Failed!`) 94 for(let compDetail of compResult.detail){ 95 if(!compDetail.compResult){ 96 console.log(`==> Expect the error in Line ${compDetail.expectLineAndCharacter.line} The ${compDetail.expectLineAndCharacter.character} character. Expect exception rules:${compDetail.expectMessageText} Actual error line ${compDetail.realLineAndCharacter.line} The ${compDetail.realLineAndCharacter.character} character. Actual exception rules:${compDetail.realMessageText} Comparison Result:Fail!`) 97 } 98 } 99 } 100 compResults["failNum"] += 1 101 compResults['detail'][rules]["failNum"] += 1 102 } 103} 104 105 106// initial configuration 107options = ts.readConfigFile('tsconfig.json', ts.sys.readFile).config.compilerOptions; 108const allPath = ['*']; 109Object.assign(options, { 110 'emitNodeModulesFiles': true, 111 'importsNotUsedAsValues': ts.ImportsNotUsedAsValues.Preserve, 112 'module': ts.ModuleKind.CommonJS, 113 'moduleResolution': ts.ModuleResolutionKind.NodeJs, 114 'noEmit': true, 115 'target': ts.ScriptTarget.ES2017, 116 'baseUrl': "/", 117 'paths': { 118 '*': allPath 119 }, 120 'lib': [ 121 'lib.es2020.d.ts' 122 ], 123 'types': [], 124 'etsLoaderPath': 'null_sdkPath', 125}); 126 127// Calling the runlinter interface 128function runLinter(rootName){ 129 newprogram = ts.createProgram({ 130 rootNames: [path.join(process.cwd(), rootName)], 131 options: options, 132 }) 133 const compilerHost = ts.createCompilerHost(newprogram.getCompilerOptions()); 134 compilerHost.getCurrentDirectory = () => process.cwd(); 135 compilerHost.getDefaultLibFileName = options => ts.getDefaultLibFilePath(options); 136 // compilerHost.resolveTypeReferenceDirectives = resolveTypeReferenceDirectives; 137 let result= ts.runArkTSLinter(newprogram, compilerHost) 138 return result 139} 140 141// Compare the difference between the expected value and the actual return value of the runlinter to determine if the test has passed 142function compareResult(expect, reality){ 143 let isPass = true 144 const itemPassList = new Array() 145 if(reality.length == 0){ 146 if(expect.length == 0){ 147 // pass 148 isPass = true 149 }else{ 150 isPass = false 151 for(let expectInfo of expect){ 152 const compInfo = { 153 'compResult':false, 154 'realLineAndCharacter':{"line": null,"character": null}, 155 'realMessageText':null, 156 'expectLineAndCharacter':{"line": expectInfo.expectLineAndCharacter.line,"character": expectInfo.expectLineAndCharacter.character}, 157 'expectMessageText':expectInfo.messageText, 158 } 159 itemPassList.push(compInfo) 160 } 161 } 162 }else{ 163 if(expect.length == 0){ 164 isPass = false 165 for(let realityInfo of reality){ 166 const { line, character } = realityInfo.file.getLineAndCharacterOfPosition(realityInfo.start) 167 const compInfo = { 168 'compResult':false, 169 'realLineAndCharacter':{"line": line + 1,"character": character + 1}, 170 'realMessageText':realityInfo.messageText, 171 'expectLineAndCharacter':{"line": null,"character": null}, 172 'expectMessageText':null, 173 } 174 itemPassList.push(compInfo) 175 } 176 }else{ 177 if( reality.length > expect.length){ 178 isPass = false 179 for(let i=0; i<reality.length; i++){ 180 const realErrorItem = reality[i] 181 const { line, character } = realErrorItem.file.getLineAndCharacterOfPosition(realErrorItem.start) 182 const realLine = {"line": line + 1,"character": character + 1} 183 const realMessageText = realErrorItem.messageText 184 let expectMessageText = null 185 let compResult = false 186 let expectLineAndCharacter = {"line": null,"character": null} 187 if( expect.length < i+1){ 188 compResult = false 189 }else{ 190 expectErrorItem = expect[i] 191 expectLineAndCharacter = {"line": expectErrorItem.expectLineAndCharacter.line,"character": expectErrorItem.expectLineAndCharacter.character} 192 expectMessageText = expectErrorItem.messageText 193 if ((expectErrorItem.expectLineAndCharacter.line === realLine.line && expectErrorItem.expectLineAndCharacter.character === realLine.character) 194 && realMessageText.includes(expectMessageText)){ 195 compResult = true 196 } 197 } 198 const compInfo = { 199 'compResult':compResult, 200 'realLineAndCharacter':realLine, 201 'realMessageText':realMessageText, 202 'expectLineAndCharacter':expectLineAndCharacter, 203 'expectMessageText':expectMessageText, 204 } 205 itemPassList.push(compInfo) 206 } 207 }else if(reality.length < expect.length){ 208 isPass = false 209 for(let i=0; i<expect.length; i++){ 210 const expectErrorItem = expect[i] 211 const expectMessageText = expectErrorItem.messageText 212 let expectLineAndCharacter = {"line": expectErrorItem.expectLineAndCharacter.line,"character": expectErrorItem.expectLineAndCharacter.character} 213 let realLine = {"line": null,"character": null} 214 let realMessageText = null 215 let compResult = false 216 if( reality.length < i+1){ 217 compResult = false 218 }else{ 219 const realErrorItem = reality[i] 220 const { line, character } = realErrorItem.file.getLineAndCharacterOfPosition(realErrorItem.start) 221 realLine = {"line": line + 1,"character": character + 1} 222 realMessageText = realErrorItem.messageText 223 if ((expectErrorItem.expectLineAndCharacter.line === realLine.line && expectErrorItem.expectLineAndCharacter.character === realLine.character) 224 && realMessageText.includes(expectMessageText)){ 225 compResult = true 226 } 227 } 228 const compInfo = { 229 'compResult':compResult, 230 'realLineAndCharacter':realLine, 231 'realMessageText':realMessageText, 232 'expectLineAndCharacter':expectLineAndCharacter, 233 'expectMessageText':expectMessageText, 234 } 235 itemPassList.push(compInfo) 236 } 237 }else{ 238 for(let i =0;i<reality.length;i++){ 239 const realErrorItem = reality[i] 240 const expectErrorItem = expect[i] 241 const expectMessageText = expectErrorItem.messageText 242 let expectLineAndCharacter = {"line": expectErrorItem.expectLineAndCharacter.line,"character": expectErrorItem.expectLineAndCharacter.character} 243 const { line, character } = realErrorItem.file.getLineAndCharacterOfPosition(realErrorItem.start) 244 const realLine = {"line": line + 1,"character": character + 1} 245 const realMessageText = realErrorItem.messageText 246 let compInfo = null; compResult = false 247 if ((expectErrorItem.expectLineAndCharacter.line === realLine.line && expectErrorItem.expectLineAndCharacter.character === realLine.character) 248 && realMessageText.includes(expectMessageText)){ 249 compResult = true 250 }else{ 251 isPass = false 252 } 253 compInfo = { 254 'compResult':compResult, 255 'realLineAndCharacter':realLine, 256 'realMessageText':realMessageText, 257 'expectLineAndCharacter':expectLineAndCharacter, 258 'expectMessageText':expectMessageText, 259 } 260 itemPassList.push(compInfo) 261 } 262 } 263 } 264 } 265 return {"status":isPass, "detail":itemPassList} 266} 267 268// output result file 269function writeResult(result){ 270 const dir = path.join(__dirname, "test_results") 271 if (!fs.existsSync(dir)) { 272 fs.mkdirSync(dir) 273 } 274 fs.writeFileSync(path.join(dir, "test_result.json"), JSON.stringify(result, null, 4)) 275} 276 277 278function run(){ 279 let interval = 0, startTime = process.uptime()*1000, endTime = startTime; 280 const pathParam = getParam() 281 let filePath = 'testcase' 282 if(pathParam){ 283 filePath = pathParam 284 } 285 let ignoreCaseConfigList = [] 286 if(fs.existsSync(ignoreCaseFilePath)){ 287 ignoreCaseConfigList = JSON.parse(fs.readFileSync(ignoreCaseFilePath)).ignoreCase 288 } 289 290 ignoreList = ignoreList.concat(ignoreCaseConfigList) 291 let filePathStats = fs.lstatSync(filePath) 292 if(!filePathStats.isDirectory()){ 293 runComp(filePath, path.basename(filePath)) 294 }else{ 295 getAllETSFiles(filePath) 296 } 297 endTime = process.uptime()*1000 298 interval = (endTime - startTime); 299 const compReportDetail = {"compDetail": compResults, "compTime": interval, "failNum": compResults.failNum, "passedNum": compResults.passedNum} 300 const testCaseSum = compReportDetail.failNum + compReportDetail.passedNum 301 compReportDetail["testCaseSum"] = testCaseSum 302 console.log(`Total number of test cases:${testCaseSum} Number of use cases passed:${compResults.passedNum} The number of use cases that failed:${compResults.failNum} Total running time:${JSON.stringify(interval).split(".")[0]}ms`) 303 if(genResultFile){ 304 writeResult(compReportDetail) 305 } 306 if (failTestCaseList.length > 0){ 307 console.log("Failed test cases:") 308 for(let testCase of failTestCaseList){ 309 console.log(testCase) 310 } 311 } 312 if(ignoreList.length>0){ 313 console.log("Ignored test cases:") 314 for(let ignoreCase of ignoreList){ 315 console.log(ignoreCase) 316 } 317 } 318 if(compReportDetail.failNum){ 319 process.exit(1) 320 } 321} 322 323// get parameters 324function getParam(){ 325 let pathArg = null 326 for(let key of process.argv){ 327 if(key.includes("-P:")){ 328 pathArg = key.replace("-P:", "") 329 } 330 if(key === "--detail" || key === "-D"){ 331 consoleDetail = true 332 } 333 if(key === "-e"){ 334 genResultFile = true 335 } 336 if(key.includes("--ignore-list:")){ 337 let ignoreStr = key.replace("--ignore-list:", "") 338 ignoreList = ignoreStr.split(",") 339 } 340 } 341 return pathArg 342} 343 344// execute 345run() 346