Add resilient dual-radio network failover

This commit is contained in:
2026-07-31 20:24:34 +02:00
parent 0a0dae144c
commit 6940cfb3a8
19 changed files with 857 additions and 11 deletions
+52
View File
@@ -0,0 +1,52 @@
import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { afterEach, describe, expect, it } from "vitest";
import type { AppConfig } from "../src/config.js";
import { consumeNetworkCommand, readNetworkStatus, requestNetworkAction } from "../src/network.js";
const directories: string[] = [];
function config(directory: string, enabled = true): AppConfig {
return {
nodeEnv: "test",
host: "127.0.0.1",
port: 8787,
databasePath: ":memory:",
sessionTtlMs: 60_000,
cookieSecure: false,
allowedOrigins: new Set(),
updateStatusPath: join(directory, "update.json"),
versionFile: join(directory, "REVISION"),
network: { enabled, statusPath: join(directory, "status.json"), commandPath: join(directory, "command.json") },
adb: { enabled: false, executable: "adb", serial: null, timeoutMs: 3_000 }
};
}
afterEach(async () => {
await Promise.all(directories.splice(0).map((directory) => rm(directory, { recursive: true, force: true })));
});
describe("network control boundary", () => {
it("writes and consumes only fixed action requests", async () => {
const directory = await mkdtemp(join(tmpdir(), "pi-car-network-test-"));
directories.push(directory);
const testConfig = config(directory);
const requested = await requestNetworkAction(testConfig, "retry-upstream", 7);
expect(JSON.parse(await readFile(testConfig.network.commandPath, "utf8"))).toMatchObject({
id: requested.id,
action: "retry-upstream",
actorUserId: 7
});
await expect(consumeNetworkCommand(testConfig.network.commandPath)).resolves.toMatchObject({ action: "retry-upstream" });
await expect(consumeNetworkCommand(testConfig.network.commandPath)).resolves.toBeNull();
});
it("rejects malformed controller status", async () => {
const directory = await mkdtemp(join(tmpdir(), "pi-car-network-test-"));
directories.push(directory);
const testConfig = config(directory);
await writeFile(testConfig.network.statusPath, '{"mode":"shell"}');
await expect(readNetworkStatus(testConfig)).resolves.toMatchObject({ supported: false, mode: "starting" });
});
});