Skip to content

Commit 5b7c4b6

Browse files
committed
refactor: migrate runSketch to strict Options object and cleanup tests
1 parent 5cc60e7 commit 5b7c4b6

12 files changed

Lines changed: 250 additions & 342 deletions

archive/debug-runner.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import { SandboxRunner } from "../server/services/sandbox-runner.ts";
33
(async () => {
44
const runner = new SandboxRunner();
55
console.log("initial state running=", runner.isRunning, "paused=", runner.isPaused);
6-
runner.runSketch(
7-
`
6+
runner.runSketch({
7+
code: `
88
void setup() {
99
Serial.begin(9600);
1010
Serial.println("BOOTED");
@@ -18,10 +18,10 @@ import { SandboxRunner } from "../server/services/sandbox-runner.ts";
1818
delay(100);
1919
}
2020
`,
21-
(line) => { console.log("[RUNNER OUT]", line); },
22-
(err) => { console.error("[RUNNER ERR]", err); },
23-
(code) => { console.log("[RUNNER EXIT]", code); },
24-
);
21+
onOutput: (line) => { console.log("[RUNNER OUT]", line); },
22+
onError: (err) => { console.error("[RUNNER ERR]", err); },
23+
onExit: (code) => { console.log("[RUNNER EXIT]", code); },
24+
});
2525
setTimeout(() => {
2626
console.log("[RUNNER] setting pin 2 to HIGH");
2727
runner.setPinValue(2, 1);

scripts/debug-runner.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import { SandboxRunner } from "../server/services/sandbox-runner.ts";
33
(async () => {
44
const runner = new SandboxRunner();
55
console.log("initial state running=", runner.isRunning, "paused=", runner.isPaused);
6-
runner.runSketch(
7-
`
6+
runner.runSketch({
7+
code: `
88
void setup() {
99
Serial.begin(9600);
1010
Serial.println("BOOTED");
@@ -18,10 +18,10 @@ import { SandboxRunner } from "../server/services/sandbox-runner.ts";
1818
delay(100);
1919
}
2020
`,
21-
(line) => { console.log("[RUNNER OUT]", line); },
22-
(err) => { console.error("[RUNNER ERR]", err); },
23-
(code) => { console.log("[RUNNER EXIT]", code); },
24-
);
21+
onOutput: (line) => { console.log("[RUNNER OUT]", line); },
22+
onError: (err) => { console.error("[RUNNER ERR]", err); },
23+
onExit: (code) => { console.log("[RUNNER EXIT]", code); },
24+
});
2525
setTimeout(() => {
2626
console.log("[RUNNER] setting pin 2 to HIGH");
2727
runner.setPinValue(2, 1);

server/routes/simulation.ws.ts

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -203,20 +203,20 @@ export function registerSimulationWebSocket(httpServer: Server, deps: Simulation
203203
logger.warn(`Could not stringify run payload for evidence: ${err instanceof Error ? err.message : String(err)}`);
204204
}
205205

206-
// Call the legacy positional signature to preserve exact runtime behavior
207-
clientState.runner.runSketch(
208-
lastCompiledCode,
209-
opts.onOutput,
210-
opts.onError,
211-
opts.onExit,
212-
opts.onCompileError,
213-
opts.onCompileSuccess,
214-
opts.onPinState,
215-
opts.timeoutSec,
216-
opts.onIORegistry,
217-
opts.onTelemetry,
218-
opts.onPinStateBatch,
219-
);
206+
clientState.runner.runSketch({
207+
code: lastCompiledCode,
208+
onOutput: opts.onOutput,
209+
onError: opts.onError,
210+
onExit: opts.onExit,
211+
onCompileError: opts.onCompileError,
212+
onCompileSuccess: opts.onCompileSuccess,
213+
onPinState: opts.onPinState,
214+
timeoutSec: opts.timeoutSec,
215+
onIORegistry: opts.onIORegistry,
216+
onTelemetry: opts.onTelemetry,
217+
onPinStateBatch: opts.onPinStateBatch,
218+
context: opts.context,
219+
});
220220
}
221221
break;
222222

server/services/sandbox-runner.ts

Lines changed: 3 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -401,48 +401,8 @@ export class SandboxRunner {
401401

402402
// Note: Duplicate flushMessageQueue removed - using single implementation above
403403

404-
async runSketch(...args: any[]) {
405-
// Supports both new object-based signature and old positional args for backward compatibility.
406-
// Normalize to RunSketchOptions object.
407-
let opts: RunSketchOptions;
408-
if (args.length === 1 && typeof args[0] === "object" && args[0] !== null && "code" in args[0]) {
409-
opts = args[0] as RunSketchOptions;
410-
} else {
411-
const [
412-
code,
413-
onOutput,
414-
onError,
415-
onExit,
416-
onCompileError,
417-
onCompileSuccess,
418-
onPinState,
419-
timeoutSec,
420-
onIORegistry,
421-
onTelemetry,
422-
onPinStateBatch,
423-
] = args as any[];
424-
425-
opts = {
426-
code,
427-
onOutput,
428-
onError,
429-
onExit,
430-
onCompileError,
431-
onCompileSuccess,
432-
onPinState,
433-
timeoutSec,
434-
onIORegistry,
435-
onTelemetry,
436-
onPinStateBatch,
437-
} as RunSketchOptions;
438-
}
439-
440-
// Evidence logging required by Task B1
441-
try {
442-
console.info("[B1-Evidence] Payload:", JSON.stringify(opts, null, 2));
443-
} catch (err) {
444-
this.logger.warn(`Could not stringify runSketch options for evidence: ${err instanceof Error ? err.message : String(err)}`);
445-
}
404+
async runSketch(options: RunSketchOptions) {
405+
const opts = options;
446406

447407
// Extract stable variables for the rest of the method
448408
const {
@@ -457,7 +417,7 @@ export class SandboxRunner {
457417
onIORegistry,
458418
onTelemetry,
459419
onPinStateBatch,
460-
} = opts as RunSketchOptions;
420+
} = opts;
461421

462422
// Lazy initialization: ensure Docker is checked and temp directory exists
463423
this.ensureDockerChecked();

tests/sandbox-stress.test.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,17 @@ function runSketchHelper(
3333
callbacks: RunSketchCallbacks,
3434
timeoutSec?: number
3535
) {
36-
return runner.runSketch(
36+
return runner.runSketch({
3737
code,
38-
callbacks.onOutput || (() => {}),
39-
callbacks.onError || (() => {}),
40-
callbacks.onExit || (() => {}),
41-
callbacks.onCompileError,
42-
callbacks.onCompileSuccess,
43-
callbacks.onPinState,
38+
onOutput: callbacks.onOutput || (() => {}),
39+
onError: callbacks.onError || (() => {}),
40+
onExit: callbacks.onExit || (() => {}),
41+
onCompileError: callbacks.onCompileError,
42+
onCompileSuccess: callbacks.onCompileSuccess,
43+
onPinState: callbacks.onPinState,
4444
timeoutSec,
45-
callbacks.onIORegistry
46-
);
45+
onIORegistry: callbacks.onIORegistry,
46+
});
4747
}
4848

4949
// Store original setTimeout for non-test operations

tests/server/pause-resume-digitalread.test.ts

Lines changed: 18 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -79,16 +79,13 @@ maybeDescribe("Pause/Resume - digitalRead after Resume", () => {
7979
};
8080

8181
// start simulation after listeners are ready
82-
runner.runSketch(
82+
runner.runSketch({
8383
code,
8484
onOutput,
8585
onError,
86-
() => {}, // onExit
87-
undefined, // onCompileError
88-
undefined, // onCompileSuccess
89-
undefined,
90-
10, // timeout
91-
);
86+
onExit: () => {},
87+
timeoutSec: 10,
88+
});
9289

9390
} catch (err) {
9491
clearTimeout(timeout);
@@ -136,9 +133,9 @@ maybeDescribe("Pause/Resume - digitalRead after Resume", () => {
136133
});
137134
}, 15000);
138135

139-
runner.runSketch(
136+
runner.runSketch({
140137
code,
141-
(line) => {
138+
onOutput: (line) => {
142139
output.push(line);
143140
const fullOutput = output.join("");
144141

@@ -183,19 +180,17 @@ maybeDescribe("Pause/Resume - digitalRead after Resume", () => {
183180
});
184181
}
185182
},
186-
(err) => {
183+
onError: (err) => {
187184
stderrLines.push(`[STDERR] ${err}`);
188185
},
189-
() => {
186+
onExit: () => {
190187
stderrLines.push(`[TEST] Process exited`);
191188
},
192-
undefined, // onCompileError
193-
undefined, // onCompileSuccess
194-
(pin, type, value) => {
189+
onPinState: (pin, type, value) => {
195190
stderrLines.push(`[PIN_STATE] pin=${pin}, type=${type}, value=${value}`);
196191
},
197-
30, // timeout
198-
);
192+
timeoutSec: 30,
193+
});
199194
});
200195

201196
// Print debug info BEFORE assertions
@@ -243,9 +238,9 @@ maybeDescribe("Pause/Resume - digitalRead after Resume", () => {
243238
reject(new Error("Timeout - did not see expected pin values after resume"));
244239
}, 30000);
245240

246-
runner.runSketch(
241+
runner.runSketch({
247242
code,
248-
(line) => {
243+
onOutput: (line) => {
249244
output.push(line);
250245
const fullOutput = output.join("");
251246

@@ -285,22 +280,20 @@ maybeDescribe("Pause/Resume - digitalRead after Resume", () => {
285280
resolve();
286281
}
287282
},
288-
(err) => {
283+
onError: (err) => {
289284
if (err.includes("[[PIN_")) return;
290285
if (err.includes("[[STDIN_RECV")) {
291286
console.log("📍 C++ stdin:", err);
292287
return;
293288
}
294289
console.error("Stderr:", err);
295290
},
296-
() => {},
297-
undefined,
298-
undefined,
299-
(pin, type, value) => {
291+
onExit: () => {},
292+
onPinState: (pin, type, value) => {
300293
console.log(`📍 Pin: ${pin}=${value} (${type})`);
301294
},
302-
30,
303-
);
295+
timeoutSec: 30,
296+
});
304297
});
305298

306299
const fullOutput = output.join("");

tests/server/pause-resume-timing.test.ts

Lines changed: 24 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@ maybeDescribe("SandboxRunner - Pause/Resume Timing", () => {
4444
reject(new Error("Test timeout"));
4545
}, 30000);
4646

47-
runner.runSketch(
47+
runner.runSketch({
4848
code,
49-
(line) => {
49+
onOutput: (line) => {
5050
// Parse time values
5151
const match = line.match(/TIME:(\d+)/);
5252
if (match) {
@@ -89,16 +89,13 @@ maybeDescribe("SandboxRunner - Pause/Resume Timing", () => {
8989
}
9090
}
9191
},
92-
(err) => {
92+
onError: (err) => {
9393
if (err.includes("[[PIN_")) return;
9494
if (err.includes("[[STDIN_RECV")) return;
9595
},
96-
() => {}, // onExit
97-
undefined, // onCompileError
98-
undefined, // onCompileSuccess
99-
undefined, // onPinStateChange
100-
15,
101-
);
96+
onExit: () => {},
97+
timeoutSec: 15,
98+
});
10299
});
103100
}, 30000);
104101

@@ -126,9 +123,9 @@ maybeDescribe("SandboxRunner - Pause/Resume Timing", () => {
126123
reject(new Error("Test timeout"));
127124
}, 30000);
128125

129-
runner.runSketch(
126+
runner.runSketch({
130127
code,
131-
(line) => {
128+
onOutput: (line) => {
132129
const match = line.match(/T:(\d+)/);
133130
if (match) {
134131
const value = parseInt(match[1]);
@@ -185,16 +182,13 @@ maybeDescribe("SandboxRunner - Pause/Resume Timing", () => {
185182
}, 300);
186183
}
187184
},
188-
(err) => {
185+
onError: (err) => {
189186
if (err.includes("[[PIN_")) return;
190187
if (err.includes("[[STDIN_RECV")) return;
191188
},
192-
() => {}, // onExit
193-
undefined,
194-
undefined,
195-
undefined,
196-
20,
197-
);
189+
onExit: () => {},
190+
timeoutSec: 20,
191+
});
198192
});
199193
});
200194

@@ -222,9 +216,9 @@ maybeDescribe("SandboxRunner - Pause/Resume Timing", () => {
222216
reject(new Error("Test timeout"));
223217
}, 30000);
224218

225-
runner.runSketch(
219+
runner.runSketch({
226220
code,
227-
(line) => {
221+
onOutput: (line) => {
228222
try {
229223
const match = line.match(/USEC:(\d+)/);
230224
if (match) {
@@ -271,16 +265,13 @@ maybeDescribe("SandboxRunner - Pause/Resume Timing", () => {
271265
reject(err);
272266
}
273267
},
274-
(err) => {
268+
onError: (err) => {
275269
if (err.includes("[[PIN_")) return;
276270
if (err.includes("[[STDIN_RECV")) return;
277271
},
278-
() => {}, // onExit
279-
undefined,
280-
undefined,
281-
undefined,
282-
15,
283-
);
272+
onExit: () => {},
273+
timeoutSec: 15,
274+
});
284275
});
285276
});
286277

@@ -310,16 +301,13 @@ maybeDescribe("SandboxRunner - Pause/Resume Timing", () => {
310301
}, 30000);
311302

312303
let sawOutput = false;
313-
runner.runSketch(
304+
runner.runSketch({
314305
code,
315-
(line) => { sawOutput = true; },
316-
() => {},
317-
() => {},
318-
undefined,
319-
undefined,
320-
undefined,
321-
15,
322-
);
306+
onOutput: (line) => { sawOutput = true; },
307+
onError: () => {},
308+
onExit: () => {},
309+
timeoutSec: 15,
310+
});
323311

324312
// wait for at least one output line (guaranteed running) before pausing
325313

0 commit comments

Comments
 (0)