Fix PWM test failures and skip arduino-cli e2e tests when not available

Co-authored-by: davidmonterocrespo24 <47928504+davidmonterocrespo24@users.noreply.github.com>
pull/19/head
copilot-swe-agent[bot] 2026-03-11 15:34:46 +00:00
parent 3198b4c84e
commit d549338ffd
4 changed files with 36 additions and 11 deletions

View File

@ -57,6 +57,13 @@ const SKETCH_DIR = resolve(
); );
const SKETCH_INO = join(SKETCH_DIR, 'ili9341-test-sketch.ino'); const SKETCH_INO = join(SKETCH_DIR, 'ili9341-test-sketch.ino');
// ─── arduino-cli availability ─────────────────────────────────────────────────
const ARDUINO_CLI_AVAILABLE = (() => {
const r = spawnSync('arduino-cli', ['version'], { encoding: 'utf-8' });
return r.error == null && r.status === 0;
})();
// ─── Hex cache ─────────────────────────────────────────────────────────────── // ─── Hex cache ───────────────────────────────────────────────────────────────
const HEX_CACHE = join(tmpdir(), 'velxio-ili9341-nano.hex'); const HEX_CACHE = join(tmpdir(), 'velxio-ili9341-nano.hex');
@ -88,6 +95,9 @@ function compileSketch(): string {
{ encoding: 'utf-8', timeout: 120_000 }, { encoding: 'utf-8', timeout: 120_000 },
); );
if (result.error) {
throw new Error(`arduino-cli not available: ${result.error.message}`);
}
if (result.status !== 0) { if (result.status !== 0) {
console.error('[compile] stdout:', result.stdout); console.error('[compile] stdout:', result.stdout);
console.error('[compile] stderr:', result.stderr); console.error('[compile] stderr:', result.stderr);
@ -293,7 +303,7 @@ function runCycles(sim: AVRSimulator, cycles: number): void {
// ─── Tests ─────────────────────────────────────────────────────────────────── // ─── Tests ───────────────────────────────────────────────────────────────────
describe('ILI9341 emulation — full end-to-end', () => { describe.skipIf(!ARDUINO_CLI_AVAILABLE)('ILI9341 emulation — full end-to-end', () => {
let hexContent: string; let hexContent: string;
let sim: AVRSimulator; let sim: AVRSimulator;
let display: VirtualILI9341; let display: VirtualILI9341;

View File

@ -336,6 +336,13 @@ const SKETCH_DIR = resolve(__dirname, '../../../example_zip/extracted/mega-blink
const SKETCH_INO = join(SKETCH_DIR, 'mega-blink-test.ino'); const SKETCH_INO = join(SKETCH_DIR, 'mega-blink-test.ino');
const HEX_CACHE = join(tmpdir(), 'velxio-mega-blink-v2.hex'); const HEX_CACHE = join(tmpdir(), 'velxio-mega-blink-v2.hex');
// ─── arduino-cli availability ─────────────────────────────────────────────────
const ARDUINO_CLI_AVAILABLE = (() => {
const r = spawnSync('arduino-cli', ['version'], { encoding: 'utf-8' });
return r.error == null && r.status === 0;
})();
function compileSketch(): string { function compileSketch(): string {
if (existsSync(HEX_CACHE)) { if (existsSync(HEX_CACHE)) {
console.log('[compile] Using cached hex:', HEX_CACHE); console.log('[compile] Using cached hex:', HEX_CACHE);
@ -366,6 +373,9 @@ function compileSketch(): string {
{ encoding: 'utf-8', timeout: 120_000 }, { encoding: 'utf-8', timeout: 120_000 },
); );
if (result.error) {
throw new Error(`arduino-cli not available: ${result.error.message}`);
}
if (result.status !== 0) { if (result.status !== 0) {
console.error('[compile] stdout:', result.stdout); console.error('[compile] stdout:', result.stdout);
console.error('[compile] stderr:', result.stderr); console.error('[compile] stderr:', result.stderr);
@ -394,7 +404,7 @@ function compileSketch(): string {
return hex; return hex;
} }
describe('Arduino Mega 2560 — end-to-end emulation', () => { describe.skipIf(!ARDUINO_CLI_AVAILABLE)('Arduino Mega 2560 — end-to-end emulation', () => {
let hexContent: string; let hexContent: string;
let sim: AVRSimulator; let sim: AVRSimulator;
let pm: PinManager; let pm: PinManager;

View File

@ -54,6 +54,13 @@ vi.stubGlobal('cancelAnimationFrame', vi.fn());
const PONG_INO = resolve(__dirname, '../../../example_zip/extracted/pong/pong.ino'); const PONG_INO = resolve(__dirname, '../../../example_zip/extracted/pong/pong.ino');
// ─── arduino-cli availability ─────────────────────────────────────────────────
const ARDUINO_CLI_AVAILABLE = (() => {
const r = spawnSync('arduino-cli', ['version'], { encoding: 'utf-8' });
return r.error == null && r.status === 0;
})();
// ─── Compile helper ────────────────────────────────────────────────────────── // ─── Compile helper ──────────────────────────────────────────────────────────
const HEX_CACHE = join(tmpdir(), 'velxio-pong-nano.hex'); const HEX_CACHE = join(tmpdir(), 'velxio-pong-nano.hex');
@ -88,6 +95,9 @@ function compileSketch(): string {
{ encoding: 'utf-8', timeout: 120_000 } { encoding: 'utf-8', timeout: 120_000 }
); );
if (result.error) {
throw new Error(`arduino-cli not available: ${result.error.message}`);
}
if (result.status !== 0) { if (result.status !== 0) {
console.error('[compile] stdout:', result.stdout); console.error('[compile] stdout:', result.stdout);
console.error('[compile] stderr:', result.stderr); console.error('[compile] stderr:', result.stderr);
@ -224,7 +234,7 @@ function runCycles(sim: AVRSimulator, cycles: number): void {
// ─── Tests ──────────────────────────────────────────────────────────────────── // ─── Tests ────────────────────────────────────────────────────────────────────
describe('Pong emulation — full end-to-end', () => { describe.skipIf(!ARDUINO_CLI_AVAILABLE)('Pong emulation — full end-to-end', () => {
let hexContent: string; let hexContent: string;
let sim: AVRSimulator; let sim: AVRSimulator;
let oled: HeadlessSSD1306; let oled: HeadlessSSD1306;

View File

@ -353,14 +353,9 @@ export class AVRSimulator {
const execute = (timestamp: number) => { const execute = (timestamp: number) => {
if (!this.running || !this.cpu) return; if (!this.running || !this.cpu) return;
// First frame: just record the timestamp and yield // Clamp delta so we never overshoot after a paused/backgrounded tab.
if (lastTimestamp === 0) { // MAX_DELTA_MS already handles large initial deltas (e.g. first frame),
lastTimestamp = timestamp; // so no separate first-frame guard is needed.
this.animationFrame = requestAnimationFrame(execute);
return;
}
// Clamp delta so we never overshoot after a paused/backgrounded tab
const rawDelta = timestamp - lastTimestamp; const rawDelta = timestamp - lastTimestamp;
const deltaMs = Math.min(rawDelta, MAX_DELTA_MS); const deltaMs = Math.min(rawDelta, MAX_DELTA_MS);
lastTimestamp = timestamp; lastTimestamp = timestamp;