test: qemu_session.py ident_attach_fail -- the identity partition unreadable (#179, #187)

A data stick hot-plugged with every read at its identity partition's first
sector (LBA 2048) failing, after a boot with no drive; it expects a message
naming the identity partition, Artemis let go (both partitions or neither,
#179), no prompt, and the same stick without the fault going on to genesis.
add_stick() takes fail_read_sector for it.

It FAILS today, and is kept so (Captain Bob, 2026-11-12: "keep the test"):
the partition attaches anyway and Zuse is minted onto it, because
blk_format_or_load_disk() ignores the header read's result and takes an
unreadable disk as blank -- filed as #187. #179 is parked: its half-attached
state cannot be reached from a disk fault. The run: logs/20261112-160050.

Not part of acceptance.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
This commit is contained in:
Claude
2026-11-12 16:15:03 +00:00
parent 90ea372859
commit ab63789e5b
3 changed files with 37 additions and 3 deletions
+34 -3
View File
@@ -87,6 +87,10 @@ the stick's, plan 2026-10-26-stick-1-screen-and-keyboard.md):
no ok> for 30 s; the new one added: the prompt
mint_fail the fixed screen; R, a stick whose writes all fail (blkdebug): "failed -- nothing
changed", the screen again; the old stick added: the prompt (Review Focus 4)
ident_attach_fail no drive at boot; a fresh data stick hot-plugged whose reads at its identity
partition's first sector (LBA 2048) fail, so that partition cannot be attached after
Artemis is: a message naming the identity partition, Artemis let go -- both or
neither (#179) -- no prompt; the same stick without the fault: genesis, the prompt
mint_part_fail as mint_fail, but only writes to the identity partition's first sector (LBA 2048)
fail: the GPT is written, then the mint fails -- "failed -- the stick was erased; Zuse
not minted", never "nothing changed" (#168); no replacement; the old stick: the prompt
@@ -133,7 +137,7 @@ ap.add_argument("--target", default="qemu") # qemu-stick: boot the PC stick
ap.add_argument("--stick-gib", type=int, default=None) # qemu-stick: the copy extended to N GiB
a = ap.parse_args()
NO_ZUSE_MODES = {"gpt_zuse", "gpt_hotplug", "gpt_foreign", "gpt_bad_crc", "gpt_bad_entries", "gpt_no_header",
NO_ZUSE_MODES = {"ident_attach_fail", "gpt_zuse", "gpt_hotplug", "gpt_foreign", "gpt_bad_crc", "gpt_bad_entries", "gpt_no_header",
"gpt_read_error", "headless", "hotplug", "midpull", "waitpull", "typeahead", "emergency",
"alttab_after_logout", "alttab_before_pull", "emergency_pull",
"screen_dark_until_login", "screen_console_after_login", "screen_dark_after_logout",
@@ -420,16 +424,20 @@ def add_zuse(n, img=None, fail_sector0=False):
drive=f"zuse{n}", id=f"zusedev{n}")
def add_stick(n, img, port, fail_writes=False, fail_sector=None):
def add_stick(n, img, port, fail_writes=False, fail_sector=None, fail_read_sector=None):
"""A USB stick added over QMP on the xHCI controller's `port` (plan 2026-10-29-stick-5, Task 4);
with fail_writes, every write to it fails (blkdebug, EIO -- Task 5's mint_fail); with fail_sector,
only writes touching that sector fail (#168's mint_part_fail)."""
only writes touching that sector fail (#168's mint_part_fail); with fail_read_sector, only reads
touching that sector fail (#179's ident_attach_fail)."""
f = {"driver": "file", "filename": img}
if fail_writes:
f = {"driver": "blkdebug", "image": f, "inject-error": [{"event": "none", "iotype": "write", "errno": 5}]}
elif fail_sector is not None:
f = {"driver": "blkdebug", "image": f,
"inject-error": [{"event": "none", "iotype": "write", "sector": fail_sector, "errno": 5}]}
elif fail_read_sector is not None:
f = {"driver": "blkdebug", "image": f,
"inject-error": [{"event": "none", "iotype": "read", "sector": fail_read_sector, "errno": 5}]}
qcmd("blockdev-add", driver="raw", **{"node-name": f"stick{n}"}, file=f)
qcmd("device_add", driver="usb-storage", bus="xhci0.0", port=str(port), drive=f"stick{n}", id=f"stickdev{n}")
@@ -929,6 +937,29 @@ elif m == "entropy":
check("[zuse@Hera] ok>", wait_for(PROMPT, 120))
check("no fault", count(r"EXCEPTION|PANIC|panic") == 0)
elif m == "ident_attach_fail":
# #179: the identity partition (LBA 2048 on a data stick) cannot be read, so it cannot be
# attached -- after Artemis has been. Both partitions or neither.
dstick = os.path.join(work, "ident-fail.img")
subprocess.run(["make", "-f", "kernel/Makefile", f"ARCH={a.arch}", "datastick", f"DATASTICK_IMG={dstick}"],
cwd=ROOT, check=True, stdout=subprocess.DEVNULL)
check("no ok> for 20 s with no drive", not wait_for(ANYPROMPT, 20))
add_stick(1, dstick, 2, fail_read_sector=2048)
check("Zuse: the stick's identity partition failed -- not used",
wait_for(r"Zuse: the stick's identity partition failed -- not used", 120), near=r"Artemis|Zuse|xhci")
check("Artemis: the stick's partition let go -- both or neither",
wait_for(r"Artemis: the stick's partition let go", 30), near=r"Artemis|Zuse|xhci")
n = count(ANYPROMPT)
check("no ok> for 20 s with the faulty stick", not wait_for(ANYPROMPT, 20, n))
qcmd("device_del", id="stickdev1")
time.sleep(3)
qcmd("blockdev-del", **{"node-name": "stick1"})
g = count(r"Zuse: genesis minted onto attached thumbdrive")
add_stick(2, dstick, 2)
check("the same stick, without the fault: genesis", wait_for(r"Zuse: genesis minted onto attached thumbdrive", 180, g),
near=r"Artemis|Zuse")
check("[zuse@Hera] ok>", wait_for(PROMPT, 60))
elif m == "hotplug":
check("no ok> for 20 s with no drive", not wait_for(ANYPROMPT, 20))
add_zuse(1)