From d27670ec39cba386f8ca5cd7a11e2c0708739086 Mon Sep 17 00:00:00 2001 From: Daniel Samson <12231216+daniel-samson@users.noreply.github.com> Date: Thu, 30 Jul 2026 06:23:31 +0100 Subject: [PATCH] tests: fix the two stale kernel self-tests the FHS boot tree broke MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit initial_ramdisk's spawn-everything sweep counted the /etc data files (devices.csv, init.csv) as spawnable programs — BadElf ever since the boot tree started ferrying them — so it now counts only the /system and /test trees. The init test waited for two raw user writes before checking the last write for the heartbeat text; init's boot chatter (heap ok, the /etc/init.csv lookup) satisfies the count long before the first beat, so it now waits for the heartbeat itself. Both cases pass again; these failures predate the build-packages work. --- system/kernel/tests.zig | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/system/kernel/tests.zig b/system/kernel/tests.zig index 5d7bb27..4741822 100644 --- a/system/kernel/tests.zig +++ b/system/kernel/tests.zig @@ -1970,15 +1970,20 @@ fn initTest(boot_information: *const BootInformation) void { }; check("init loaded and spawned as a process", spawned); - // Wait (real time) for at least two heartbeats — proving it runs, writes, - // and sleeps repeatedly (init sleeps ~1 s between beats). + // Wait (real time) until the LAST write is a heartbeat — proving init got + // through its boot chatter (heap ok, the /etc/init.csv lookup) and settled + // into its beat-and-sleep loop (~1 s between beats). Waiting on the text + // rather than a raw write count: the boot chatter alone satisfies a count, + // which is exactly the too-early check that used to fail here. scheduler.setPriority(1); - const deadline = architecture.millis() + 8000; - while (process.write_count < 2 and architecture.millis() < deadline) scheduler.yield(); - scheduler.setPriority(4); - const prefix = "init: heartbeat"; - const beat_ok = bufferHas(prefix); + const deadline = architecture.millis() + 8000; + var beat_ok = false; + while (!beat_ok and architecture.millis() < deadline) { + beat_ok = bufferHas(prefix); + scheduler.yield(); + } + scheduler.setPriority(4); check("init produced repeated heartbeats (>=2)", process.write_count >= 2); check("heartbeat text arrived intact", beat_ok); check("heartbeats came from user mode (CPL 3)", process.write_from_user); @@ -2792,15 +2797,24 @@ fn initialRamdiskTest(boot_information: *const BootInformation) void { process.write_count = 0; process.write_from_user = false; + var programs: u32 = 0; var spawned: u32 = 0; var i: u32 = 0; while (i < rd.count) : (i += 1) { const item = rd.entry(i) orelse continue; + // The FHS boot tree ferries data files too (/etc/devices.csv, + // /etc/init.csv — served read-only by the kernel VFS, never spawned); + // only the /system and /test trees hold programs, so only those count + // toward the spawn-everything sweep. + const is_program = std.mem.startsWith(u8, item.name, "/system/") or + std.mem.startsWith(u8, item.name, "/test/"); + if (!is_program) continue; + programs += 1; if (process.spawnProcess(item.blob, 4, &.{item.name})) spawned += 1 else |err| { log("DANOS-INITRD-ERR: {s}: {s}\n", .{ item.name, @errorName(err) }); } } - check("every initial_ramdisk binary spawned", spawned == rd.count); + check("every initial_ramdisk program spawned", programs >= 1 and spawned == programs); // Wait for the spawned programs to run and make syscalls (they write + sleep). scheduler.setPriority(1);