From 501d9990fe2bfc4fc1a97247a9bf40a74733e42c Mon Sep 17 00:00:00 2001 From: Tom Lauwaerts Date: Thu, 4 Jun 2026 15:11:17 +0200 Subject: [PATCH 1/3] Fix uncaught timeout and improve output --- src/framework/Testee.ts | 8 +++++++- src/framework/Verifier.ts | 4 +--- src/reporter/Style.ts | 2 ++ src/reporter/describers/Describer.ts | 2 ++ src/util/util.ts | 4 ++++ 5 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/framework/Testee.ts b/src/framework/Testee.ts index e53a575..3bcf6ab 100644 --- a/src/framework/Testee.ts +++ b/src/framework/Testee.ts @@ -14,6 +14,7 @@ import {WASM} from '../sourcemap/Wasm'; import {DummyProxy} from '../testbeds/Emulator'; import {ScenarioResult, Skipped, StepOutcome, SuiteResult} from '../reporter/Results'; import {Verifier} from './Verifier'; +import {stringify} from "../util/util"; export function timeout(label: string, time: number, promise: Promise): Promise { if (time === 0) { @@ -211,9 +212,10 @@ export class Testee { // TODO unified with testbed interface } for (const step of description.steps ?? []) { + const verifier: Verifier = new Verifier(step); + /** Perform the step and check if expectations were met */ await this.step(step.title, testee.timeout, async function () { - const verifier: Verifier = new Verifier(step); if (testee.bed(step.target ?? Target.supervisor) === undefined) { testee.states.set(description.title, verifier.error('Cannot run test: no debugger connection.')); return; @@ -246,6 +248,10 @@ export class Testee { // TODO unified with testbed interface previous = actual; } + testee.states.set(description.title, result); + scenarioResult.add(result); + }).catch((error: Error | string) => { + const result = verifier.error(stringify(error)); testee.states.set(description.title, result); scenarioResult.add(result); }); diff --git a/src/framework/Verifier.ts b/src/framework/Verifier.ts index e20a031..b233575 100644 --- a/src/framework/Verifier.ts +++ b/src/framework/Verifier.ts @@ -45,9 +45,7 @@ export class Verifier { } public error(clarification: string): StepOutcome { - const result: StepOutcome = new StepOutcome(this.step); - result.update(Outcome.succeeded); - return result.update(Outcome.error, clarification); + return new StepOutcome(this.step).update(clarification.includes('timeout') ? Outcome.timedout : Outcome.error, clarification); } private expectPrimitive(actual: T, expected: T): StepOutcome { diff --git a/src/reporter/Style.ts b/src/reporter/Style.ts index 0fce532..cf76385 100644 --- a/src/reporter/Style.ts +++ b/src/reporter/Style.ts @@ -20,6 +20,7 @@ interface Labels { success: string; skipped: string; + timeout: string; failure: string; error: string; } @@ -68,6 +69,7 @@ export class Plain implements Style { suiteSkipped: ' SKIPPED ', success: ' PASS ', skipped: ' SKIP ', + timeout: ' TIMEOUT ', failure: ' FAIL ', error: ' ERROR ' } diff --git a/src/reporter/describers/Describer.ts b/src/reporter/describers/Describer.ts index 2601212..beee1f8 100644 --- a/src/reporter/describers/Describer.ts +++ b/src/reporter/describers/Describer.ts @@ -35,6 +35,8 @@ export class StepDescriber extends Describer { case Outcome.uncommenced: case Outcome.skipped: return [`${style.colors.skipped(style.labels.skipped)} ${this.item.name}`]; + case Outcome.timedout: + return [`${style.colors.skipped(style.labels.timeout)} ${this.item.name}`]; case Outcome.error: case Outcome.failed: default: diff --git a/src/util/util.ts b/src/util/util.ts index 066c94f..22b82ad 100644 --- a/src/util/util.ts +++ b/src/util/util.ts @@ -12,4 +12,8 @@ export function find(regex: RegExp, input: string) { return ''; } return match[1]; +} + +export function stringify(chunk: Error | string): string { + return chunk instanceof Error ? chunk.message : chunk; } \ No newline at end of file From 187e44f742b1e4c0e647a90b692eeb5ca97118a0 Mon Sep 17 00:00:00 2001 From: Tom Lauwaerts Date: Thu, 4 Jun 2026 15:14:03 +0200 Subject: [PATCH 2/3] Make timeouts count as failures --- src/reporter/Results.ts | 2 +- src/reporter/describers/Describer.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/reporter/Results.ts b/src/reporter/Results.ts index 0704a5f..835186c 100644 --- a/src/reporter/Results.ts +++ b/src/reporter/Results.ts @@ -73,7 +73,7 @@ abstract class AbstractAggregateResult implements AggregateResult { } private failing(): boolean { - return this.subOutcomes.some((outcome) => outcome.outcome === Outcome.failed); + return this.subOutcomes.some((outcome) => outcome.outcome === Outcome.failed || outcome.outcome === Outcome.timedout); } } diff --git a/src/reporter/describers/Describer.ts b/src/reporter/describers/Describer.ts index beee1f8..3313316 100644 --- a/src/reporter/describers/Describer.ts +++ b/src/reporter/describers/Describer.ts @@ -36,7 +36,7 @@ export class StepDescriber extends Describer { case Outcome.skipped: return [`${style.colors.skipped(style.labels.skipped)} ${this.item.name}`]; case Outcome.timedout: - return [`${style.colors.skipped(style.labels.timeout)} ${this.item.name}`]; + return [`${style.colors.failure(style.labels.timeout)} ${this.item.name}`]; case Outcome.error: case Outcome.failed: default: From f44b5657e4ee6840cadb4c23dffd622f83b7a3da Mon Sep 17 00:00:00 2001 From: Tom Lauwaerts Date: Thu, 4 Jun 2026 15:23:09 +0200 Subject: [PATCH 3/3] Fix type error in extract type --- src/messaging/Parsers.ts | 6 ++++-- tests/unit/parsing.test.ts | 21 ++++++++++++++++++--- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/messaging/Parsers.ts b/src/messaging/Parsers.ts index 4babeff..0f93629 100644 --- a/src/messaging/Parsers.ts +++ b/src/messaging/Parsers.ts @@ -68,8 +68,10 @@ export function signed(value: bigint, bits = 32) { } function extractType(object: {value: bigint | number, type: any}): Type { - if (isNaN(object.value)) return WASM.Special.nan; - if (object.value === Infinity) return WASM.Special.infinity; + if (typeof object.value === 'number') { + if (Number.isNaN(object.value)) return WASM.Special.nan; + if (object.value === Infinity) return WASM.Special.infinity; + } return WASM.typing.get(object.type.toLowerCase()) ?? WASM.Special.unknown; } diff --git a/tests/unit/parsing.test.ts b/tests/unit/parsing.test.ts index 73b3efa..10c3df6 100644 --- a/tests/unit/parsing.test.ts +++ b/tests/unit/parsing.test.ts @@ -1,7 +1,9 @@ import test from 'ava'; -import {signed, stateParser} from "../../src/messaging/Parsers"; -import {WARDuino} from "../../src"; +import {invokeParser, signed, stateParser} from "../../src/messaging/Parsers"; +import {Exception, WARDuino} from "../../src"; +import {WASM} from "../../src/sourcemap/Wasm"; import State = WARDuino.State; +import Type = WASM.Type; /** * Check unsigned 32-bit integer to signed conversion @@ -53,4 +55,17 @@ test('[state parser] : 64-bit integer precision', t => { const state: State = stateParser(`{\"stack\": [{\"idx\":0,\"type\":\"i32\",\"value\":${value}}]}\n`); t.true(equality(state.stack?.[0].value, value)); } -}); \ No newline at end of file +}); + +test('[invoke parser] : i64 signed conversion', t => { + const result: WASM.Value | Exception = invokeParser('{"stack": [{"idx":0,"type":"i64","value":18446744073709551615}]}\n'); + + if ('text' in result) { // check if exception + t.fail(`Expected parsed value, got exception: ${result.text}`); + return; + } + + t.is(result.type, WASM.Integer.i64); + t.is(result.value, -1n); +}); +