feat: add address sanitizer, persistent FIFO fds, and latency test

This commit is contained in:
Loic Coenen
2026-05-24 09:22:22 +00:00
committed by Loic Coenen (aider)
parent 0537263a7a
commit dd67576c45
6 changed files with 217 additions and 69 deletions

View File

@@ -71,8 +71,8 @@ function writeFifoCommand(cmd: string): void {
function setupTest() {
process.stdout.write(" Killing stale processes...\n");
runNoThrow("pkill -9 -x looper");
runNoThrow("pkill -9 -x looper-client");
runNoThrow("pkill -15 -x looper");
runNoThrow("pkill -15 -x looper-client");
runNoThrow("pkill -9 -x jack_capture");
runNoThrow("tmux kill-session -t looper 2>/dev/null || true");
process.stdout.write(" Checking JACK...\n");
@@ -90,8 +90,8 @@ function teardownTest() {
fs.closeSync(cmdFifoFd);
cmdFifoFd = null;
}
runNoThrow("pkill -9 -x looper");
runNoThrow("pkill -9 -x looper-client");
runNoThrow("pkill -15 -x looper");
runNoThrow("pkill -15 -x looper-client");
runNoThrow("pkill -9 -x jack_capture");
runNoThrow("tmux kill-session -t looper");
}
@@ -911,13 +911,13 @@ async function testStressRandomUsage(): Promise<void> {
throw new Error("Engine crash during stress test");
}
// Check TUI pane integrity (nonempty, has selection line)
// Check TUI pane integrity (nonempty, at least has header and a cell)
let pane = tmuxCapturePane("looper", "0");
if (!pane || pane.trim() === "") {
await wait(200);
pane = tmuxCapturePane("looper", "0");
}
if (!pane || !pane.includes("Selected:")) {
if (!pane || !pane.includes("JACK Looper") || !pane.includes(" 0")) {
console.log(` FAIL: TUI pane appears corrupted at key ${keysSent}`);
console.log(" Pane:\n" + (pane ? pane.slice(0, 1000) : "(empty)"));
teardownTest();
@@ -940,6 +940,67 @@ async function testStressRandomUsage(): Promise<void> {
teardownTest();
}
async function testKeyPressLatency(): Promise<void> {
console.log("\nTest: KEY PRESS LATENCY (50 toggles, check for exponential slowdown)");
setupTest();
const engine = await startEngine();
await startClientInTmux();
openCmdFifo();
await wait(500);
const ITERATIONS = 50;
const LATENCY_WARN = 500; // warn if >500ms
const LATENCY_FAIL = 5000; // fail if >5s
let latencies: number[] = [];
let prevState = "IDLE";
for (let i = 0; i < ITERATIONS; i++) {
// Determine which state we expect after toggle
const expectNext = (prevState === "IDLE") ? "R" : "L";
const startTime = Date.now();
tmuxSendKeys("looper", "0", "t");
const pane = await waitForPaneText(expectNext, 10000);
const elapsed = Date.now() - startTime;
latencies.push(elapsed);
// Log periodic summary
if (i % 10 === 9) {
const avg = latencies.slice(i-9, i+1).reduce((a,b)=>a+b,0) / 10;
console.log(` Iteration ${i+1}: avg last 10 = ${avg.toFixed(0)} ms, last = ${elapsed} ms`);
}
if (elapsed > LATENCY_FAIL) {
console.log(` FAIL: Iteration ${i+1} latency ${elapsed} ms exceeds ${LATENCY_FAIL} ms`);
engine.kill(); teardownTest();
throw new Error(`Latency exceeded fail threshold at iteration ${i+1}`);
}
if (elapsed > LATENCY_WARN) {
console.log(` WARN: Iteration ${i+1} latency ${elapsed} ms > ${LATENCY_WARN} ms (possible slowdown)`);
}
// Toggle state for next expectation
prevState = (prevState === "IDLE") ? "LOOPING" : "IDLE";
await wait(200); // brief cooldown
}
// Check for trend: if last 10 avg > 3x first 10 avg → exponential
const first10Avg = latencies.slice(0,10).reduce((a,b)=>a+b,0) / 10;
const last10Avg = latencies.slice(-10).reduce((a,b)=>a+b,0) / 10;
console.log(` First 10 avg: ${first10Avg.toFixed(0)} ms, Last 10 avg: ${last10Avg.toFixed(0)} ms`);
if (last10Avg > 3 * first10Avg && last10Avg > 500) {
console.log(` FAIL: Latency grew from ${first10Avg.toFixed(0)} ms to ${last10Avg.toFixed(0)} ms (exponential pattern)`);
engine.kill(); teardownTest();
throw new Error("Exponential latency increase");
}
console.log(" PASS: No exponential latency growth");
engine.kill();
teardownTest();
}
async function main(): Promise<void> {
console.log("=== Looper E2E Tests ===\n");
@@ -956,7 +1017,8 @@ async function main(): Promise<void> {
*/
testRecordOnHighRow,
testRecordMoveRecord,
testStressRandomUsage
testStressRandomUsage,
testKeyPressLatency
];
let passCount = 0;
let failCount = 0;