code wiki / _hdl_build / nx_email_mailbox_gate.nx
nx_email_mailbox_gate.nx source
↩ module page · 120 lines · 5791 B
1// nx_email_mailbox_gate.nx -- GATE for EMAIL R3 (mailbox store, nx_email_mailbox).
2//
3// REAL filesystem I/O against a fresh segment-store dir (the harness
4// rm -rf + mkdir's knowledge/status/mbox_test before each run):
5//
6// COMPLETENESS : deliver two messages; fetch each back BYTE-IDENTICAL;
7// fetch a never-delivered id -> absent.
8// SOFT-DELETE : tombstone msg-001; it disappears from the current
9// view (fetch -> tombstoned, exists -> 0) while msg-002
10// is unaffected (per-key isolation).
11// HISTORY : after delete, msg-001 still has 2 retained versions
12// (put + tombstone) -- Cardinal 13, nothing erased.
13//
14// Evidence -> knowledge/status/email_mailbox.log
15// (MBOXGATE authored=organ ... verdict=GREEN)
16// license_tier: ORIGINAL
17import "nx_email_mailbox.nx"
18import "nx_syscalls.nx"
19import "nx_gate_verdict.nx"
20
21const MBOX_LOG: *u8 = "knowledge/status/email_mailbox.log"
22const MBOX_PREFIX: *u8 = "knowledge/status/mbox_test/"
23
24func ew(fd: i64, s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(fd, s, n); return 0 }
25func ewn(fd: i64, v: i64) -> i64 {
26 let b: *u8 = sys_mmap(28); var m: i64 = v
27 if m < 0 { m = 0 - m; sys_write(fd, "-" as *u8, 1) }
28 let t: *u8 = sys_mmap(28); var k: i64 = 0
29 if m == 0 { t[0] = 48; k = 1 }
30 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
31 var i: i64 = 0; while i < k { b[i] = t[k - 1 - i]; i = i + 1 }
32 sys_write(fd, b, k); return 0
33}
34func epf(fd: i64, label: *u8, pass: i64) -> i64 { ew(fd, label); if pass == 1 { ew(fd, "PASS" as *u8) } else { ew(fd, "FAIL" as *u8) } return 0 }
35func slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
36func memeq(a: *u8, b: *u8, len: i64) -> i64 { var i: i64 = 0; while i < len { if a[i] != b[i] { return 0 } i = i + 1 } return 1 }
37
38func main() -> i64 {
39 var ok: i64 = 1
40 // self-reset for idempotency (rule 10): ensure the store dir exists and
41 // empty its manifest so re-runs don't accumulate stale segments. The
42 // fixed segids 1/2/3 cause ss_write_seg (O_TRUNC) to overwrite seg files.
43 sys_mkdir("knowledge/status/mbox_test" as *u8, 511)
44 let rfd: i64 = sys_openat_wr("knowledge/status/mbox_test/manifest.txt" as *u8, 420)
45 if rfd >= 0 { sys_close(rfd) }
46 let pp: *i64 = sys_mmap(8) as *i64
47 let ll: *i64 = sys_mmap(8) as *i64
48
49 let msg1: *u8 = "Subject: Hello\r\nFrom: a@nishi.test\r\nMessage-ID: <msg-001>\r\n\r\nFirst message body.\r\n" as *u8
50 let msg2: *u8 = "Subject: Second\r\nFrom: b@nishi.test\r\nMessage-ID: <msg-002>\r\n\r\nSecond message body here.\r\n" as *u8
51 let m1len: i64 = slen(msg1)
52 let m2len: i64 = slen(msg2)
53
54 // deliver two
55 if nx_mbox_deliver(MBOX_PREFIX, "msg-001" as *u8, msg1, m1len, 1) != 0 { ok = 0 }
56 if nx_mbox_deliver(MBOX_PREFIX, "msg-002" as *u8, msg2, m2len, 2) != 0 { ok = 0 }
57
58 // fetch each back byte-identical
59 var fetch1: i64 = 0
60 if nx_mbox_fetch(MBOX_PREFIX, "msg-001" as *u8, pp, ll) == 1 {
61 if ll[0] == m1len && memeq(pp[0] as *u8, msg1, m1len) == 1 { fetch1 = 1 }
62 }
63 if fetch1 != 1 { ok = 0 }
64 var fetch2: i64 = 0
65 if nx_mbox_fetch(MBOX_PREFIX, "msg-002" as *u8, pp, ll) == 1 {
66 if ll[0] == m2len && memeq(pp[0] as *u8, msg2, m2len) == 1 { fetch2 = 1 }
67 }
68 if fetch2 != 1 { ok = 0 }
69
70 // absent id
71 var absent: i64 = 0
72 if nx_mbox_fetch(MBOX_PREFIX, "msg-999" as *u8, pp, ll) == (0 - 1) { absent = 1 } else { ok = 0 }
73
74 // soft-delete msg-001
75 if nx_mbox_delete(MBOX_PREFIX, "msg-001" as *u8, 3) != 0 { ok = 0 }
76 var softdel: i64 = 0
77 if nx_mbox_fetch(MBOX_PREFIX, "msg-001" as *u8, pp, ll) == 0 { softdel = 1 } else { ok = 0 }
78 let ex1: i64 = nx_mbox_exists(MBOX_PREFIX, "msg-001" as *u8)
79 let ex2: i64 = nx_mbox_exists(MBOX_PREFIX, "msg-002" as *u8)
80 var isolation: i64 = 0
81 if ex1 == 0 && ex2 == 1 { isolation = 1 } else { ok = 0 }
82
83 // history retained (put + tombstone)
84 let hist: i64 = nx_mbox_history_count(MBOX_PREFIX, "msg-001" as *u8)
85 var history_ok: i64 = 0
86 if hist == 2 { history_ok = 1 } else { ok = 0 }
87
88 // msg-002 still fetchable after deleting msg-001
89 var survive: i64 = 0
90 if nx_mbox_fetch(MBOX_PREFIX, "msg-002" as *u8, pp, ll) == 1 { survive = 1 } else { ok = 0 }
91
92 var fd: i64 = 1
93 while fd >= 1 {
94 ew(fd, "MBOXGATE authored=organ store=nx_seg_store " as *u8)
95 epf(fd, "fetch1_byteexact=" as *u8, fetch1)
96 epf(fd, " fetch2_byteexact=" as *u8, fetch2)
97 epf(fd, " absent_negctrl=" as *u8, absent)
98 epf(fd, " softdelete=" as *u8, softdel)
99 ew(fd, " exists_after_delete=" as *u8); ewn(fd, ex1)
100 epf(fd, " per_key_isolation=" as *u8, isolation)
101 ew(fd, " history_versions=" as *u8); ewn(fd, hist)
102 epf(fd, " history_retained=" as *u8, history_ok)
103 epf(fd, " neighbor_survives=" as *u8, survive)
104 if ok == 1 { ew(fd, " verdict=GREEN\n" as *u8) } else { ew(fd, " verdict=RED\n" as *u8) }
105 if fd == 1 {
106 let lf: i64 = sys_openat_append(MBOX_LOG, 420)
107 if lf >= 1 { fd = lf } else { fd = 0 }
108 } else { sys_close(fd); fd = 0 }
109 }
110
111 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check
112 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled
113 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify.
114 let ctr__dry: *i64 = gv_ctr()
115 ctr__dry[0] = ok
116 ctr__dry[1] = 1
117 let rc__dry: i64 = gv_verdict("EMAIL-MAILBOX-GATE" as *u8, ctr__dry, "teeth unchanged; verdict emission migrated onto the shared base class" as *u8)
118 sys_exit(rc__dry)
119 return rc__dry
120}