fix(tstest): Improve timeout and error handling in test execution along with TAP parser timeout logic improvements.

This commit is contained in:
2025-05-24 02:22:34 +00:00
parent 23addc2d2f
commit 63280e4a9a
4 changed files with 49 additions and 14 deletions

View File

@@ -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;