From f9ac5b2e0dfe20ee64a7c9fef2da1abd096b9bed Mon Sep 17 00:00:00 2001 From: multipleof4 Date: Fri, 26 Sep 2025 07:34:46 -0700 Subject: [PATCH] Fix: Implement global try/catch to log all errors --- test_runner.js | 144 ++++++++++++++++++++++++++----------------------- 1 file changed, 76 insertions(+), 68 deletions(-) diff --git a/test_runner.js b/test_runner.js index efa37fc..c7c1dae 100644 --- a/test_runner.js +++ b/test_runner.js @@ -44,90 +44,98 @@ function generateMarkdownReport(results) { return report; } -function generateBuildFailureReport(error) { - let report = `# Hi Language Test Results\n\n`; - report += `**Run at:** ${new Date().toISOString()}\n\n`; - report += `| Test Case | Status |\n`; - report += `|-----------|--------|\n`; - report += `| Build Step | ❌ FAIL |\n`; - report += `\n---\n\n## Failures\n\n`; - report += `### \`Build Step\`\n\n`; - report += `**Reason:** Master, failed to build parser from \`grammar.ne\`.\n\n`; - report += `**Error:**\n\`\`\`\n${error.stderr || error.message}\n\`\`\`\n\n`; - report += `---\n\n`; - return report; +function generateCrashReport(error, step) { + let report = `# Hi Language Test Results\n\n`; + report += `**Run at:** ${new Date().toISOString()}\n\n`; + report += `| Test Case | Status |\n`; + report += `|-----------|--------|\n`; + report += `| ${step} | ❌ FAIL |\n`; + report += `\n---\n\n## Failures\n\n`; + report += `### \`${step}\`\n\n`; + report += `**Reason:** Master, the test runner encountered a fatal error.\n\n`; + report += `**Error:**\n\`\`\`\n${error.stack || error.message}\n\`\`\`\n\n`; + report += `---\n\n`; + return report; } async function run() { try { - console.log("Building parser from grammar, Master..."); - execSync('npm run build-parser'); - } catch (buildError) { - console.error('Master, the parser build failed.'); - const report = generateBuildFailureReport(buildError); - writeFileSync(resultsFile, report); - console.log(`Failure report written to ${resultsFile}`); - process.exit(1); - return; - } - - // Build succeeded, now we can safely import and run tests. - const { hi2js } = await import('./transpiler.js'); - - const testFiles = readdirSync(srcDir).filter(file => file.endsWith('.hi')); - const results = []; - - console.log("Running Hi language tests, Master..."); - - for (const file of testFiles) { - const testCaseName = basename(file, '.hi'); - const hiFilePath = join(srcDir, file); - const expectedOutputPath = join(expectedDir, `${testCaseName}.txt`); - - const hiCode = readFileSync(hiFilePath, 'utf-8'); - const expectedOutput = readFileSync(expectedOutputPath, 'utf-8').trim(); - - let jsCode = ''; + // 1. Build Step try { - jsCode = hi2js(hiCode); - const actualOutput = execSync('node', { - input: jsCode, - encoding: 'utf-8' - }).trim(); + console.log("Building parser from grammar, Master..."); + execSync('npm run build-parser'); + } catch (buildError) { + throw { step: 'Build Step', error: buildError.stderr || buildError.message }; + } - if (actualOutput === expectedOutput) { - results.push({ name: testCaseName, status: '✅ PASS' }); - } else { + // 2. Transpiler Import & Test Execution + const { hi2js } = await import('./transpiler.js'); + + const testFiles = readdirSync(srcDir).filter(file => file.endsWith('.hi')); + const results = []; + + console.log("Running Hi language tests, Master..."); + + for (const file of testFiles) { + const testCaseName = basename(file, '.hi'); + const hiFilePath = join(srcDir, file); + const expectedOutputPath = join(expectedDir, `${testCaseName}.txt`); + + const hiCode = readFileSync(hiFilePath, 'utf-8'); + const expectedOutput = readFileSync(expectedOutputPath, 'utf-8').trim(); + + let jsCode = ''; + try { + jsCode = hi2js(hiCode); + const actualOutput = execSync('node', { + input: jsCode, + encoding: 'utf-8' + }).trim(); + + if (actualOutput === expectedOutput) { + results.push({ name: testCaseName, status: '✅ PASS' }); + } else { + results.push({ + name: testCaseName, + status: '❌ FAIL', + reason: 'Output mismatch', + expected: expectedOutput, + actual: actualOutput, + jsCode: jsCode + }); + } + } catch (error) { results.push({ name: testCaseName, status: '❌ FAIL', - reason: 'Output mismatch', - expected: expectedOutput, - actual: actualOutput, + reason: 'Transpilation or execution error', + error: error.message, jsCode: jsCode }); } - } catch (error) { - results.push({ - name: testCaseName, - status: '❌ FAIL', - reason: 'Transpilation or execution error', - error: error.message, - jsCode: jsCode - }); } - } - const markdownReport = generateMarkdownReport(results); - writeFileSync(resultsFile, markdownReport); + const markdownReport = generateMarkdownReport(results); + writeFileSync(resultsFile, markdownReport); - console.log(`Test run complete. Results written to ${resultsFile}`); + console.log(`Test run complete. Results written to ${resultsFile}`); - if (results.some(r => r.status.includes('FAIL'))) { - console.log("Some tests failed, Master."); - process.exit(1); - } else { - console.log("All tests passed, Master."); + if (results.some(r => r.status.includes('FAIL'))) { + console.log("Some tests failed, Master."); + process.exit(1); + } else { + console.log("All tests passed, Master."); + } + } catch (e) { + // This is the global catch block for any fatal error. + const step = e.step || 'Initialization Step'; + const error = e.error || e; + console.error(`Master, a fatal error occurred during the ${step}.`); + console.error(error); + const report = generateCrashReport(error, step); + writeFileSync(resultsFile, report); + console.log(`Failure report written to ${resultsFile}`); + process.exit(1); } }