fix(tstest): Improve timeout and error handling in test execution along with TAP parser timeout logic improvements.
This commit is contained in:
		| @@ -156,8 +156,9 @@ export class TsTest { | ||||
|       let timeoutId: NodeJS.Timeout; | ||||
|        | ||||
|       const timeoutPromise = new Promise<void>((_resolve, reject) => { | ||||
|         timeoutId = setTimeout(() => { | ||||
|           execResultStreaming.childProcess.kill('SIGTERM'); | ||||
|         timeoutId = setTimeout(async () => { | ||||
|           // Use smartshell's terminate() to kill entire process tree | ||||
|           await execResultStreaming.terminate(); | ||||
|           reject(new Error(`Test file timed out after ${this.timeoutSeconds} seconds`)); | ||||
|         }, timeoutMs); | ||||
|       }); | ||||
| @@ -172,6 +173,12 @@ export class TsTest { | ||||
|       } catch (error) { | ||||
|         // Handle timeout error | ||||
|         tapParser.handleTimeout(this.timeoutSeconds); | ||||
|         // Ensure entire process tree is killed if still running | ||||
|         try { | ||||
|           await execResultStreaming.kill(); // This kills the entire process tree with SIGKILL | ||||
|         } catch (killError) { | ||||
|           // Process tree might already be dead | ||||
|         } | ||||
|       } | ||||
|     } else { | ||||
|       await tapParser.handleTapProcess(execResultStreaming.childProcess); | ||||
| @@ -296,6 +303,7 @@ export class TsTest { | ||||
|     ); | ||||
|      | ||||
|     // Handle timeout if specified | ||||
|     let hasTimedOut = false; | ||||
|     if (this.timeoutSeconds !== null) { | ||||
|       const timeoutMs = this.timeoutSeconds * 1000; | ||||
|       let timeoutId: NodeJS.Timeout; | ||||
| @@ -315,19 +323,36 @@ export class TsTest { | ||||
|         clearTimeout(timeoutId); | ||||
|       } catch (error) { | ||||
|         // Handle timeout error | ||||
|         hasTimedOut = true; | ||||
|         tapParser.handleTimeout(this.timeoutSeconds); | ||||
|       } | ||||
|     } else { | ||||
|       await evaluatePromise; | ||||
|     } | ||||
|      | ||||
|     await this.smartbrowserInstance.stop(); | ||||
|     await server.stop(); | ||||
|     wss.close(); | ||||
|     // Always clean up resources, even on timeout | ||||
|     try { | ||||
|       await this.smartbrowserInstance.stop(); | ||||
|     } catch (error) { | ||||
|       // Browser might already be stopped | ||||
|     } | ||||
|      | ||||
|     try { | ||||
|       await server.stop(); | ||||
|     } catch (error) { | ||||
|       // Server might already be stopped | ||||
|     } | ||||
|      | ||||
|     try { | ||||
|       wss.close(); | ||||
|     } catch (error) { | ||||
|       // WebSocket server might already be closed | ||||
|     } | ||||
|      | ||||
|     console.log( | ||||
|       `${cs('=> ', 'blue')} Stopped ${cs(fileNameArg, 'orange')} chromium instance and server.` | ||||
|     ); | ||||
|     // lets create the tap parser | ||||
|     // Always evaluate final result (handleTimeout just sets up the test state) | ||||
|     await tapParser.evaluateFinalResult(); | ||||
|     return tapParser; | ||||
|   } | ||||
| @@ -351,7 +376,7 @@ export class TsTest { | ||||
|        | ||||
|       // Get all .log files in log directory (not in subdirectories) | ||||
|       const files = await plugins.smartfile.fs.listFileTree(logDir, '*.log'); | ||||
|       const logFiles = files.filter(file => !file.includes('/')); | ||||
|       const logFiles = files.filter((file: string) => !file.includes('/')); | ||||
|        | ||||
|       if (logFiles.length === 0) { | ||||
|         return; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user