code wiki / _hdl_build / nx_siteedit_history_gate.nx
nx_siteedit_history_gate.nx source
↩ module page · 90 lines · 5904 B
1// nx_siteedit_history_gate.nx -- proves the revision-history enumeration (nx_siteedit_history) against a REAL
2// fixture directory in /tmp: only `<basename>.v<digits>` snapshots are listed (noise .new/.vXY/other excluded),
3// newest-first ordering, dir-split + version-path building. license_tier: ORIGINAL
4import "nx_siteedit_history.nx"
5
6func gh_w(s: *u8) -> i64 { sys_write(1, s, sh_slen(s)); return 0 }
7func gh_wn(v: i64) -> i64 { let b: *u8 = sys_mmap(32); let o: i64 = sh_catn(b, 0, v); b[o] = 10 as u8; sys_write(1, b, o + 1); return 0 }
8func gh_eq(name: *u8, got: i64, want: i64) -> i64 {
9 if got == want { gh_w(" ok " as *u8); gh_w(name); gh_w("\n" as *u8); return 1 }
10 gh_w(" FAIL " as *u8); gh_w(name); gh_w(" got=" as *u8); gh_wn(got); return 0
11}
12func gh_writefile(path: *u8, content: *u8) -> i64 {
13 let fd: i64 = sys_openat_wr(path, 0x1a4)
14 if fd < 0 { return 0 - 1 }
15 sys_write(fd, content, sh_slen(content))
16 sys_close(fd)
17 return 0
18}
19// strcmp for the dir-split assertion
20func gh_streq(a: *u8, b: *u8) -> i64 {
21 var i: i64 = 0
22 while a[i] != (0 as u8) { if (a[i] as i64) != (b[i] as i64) { return 0 } i = i + 1 }
23 if b[i] != (0 as u8) { return 0 }
24 return 1
25}
26
27func main(argc: i64, argv: *i64) -> i64 {
28 gh_w("== nx_siteedit_history_gate ==\n" as *u8)
29 var pass: i64 = 0
30 var total: i64 = 0
31
32 // ---- fixture dir + snapshot files (+ noise). Idempotent: fixed names, O_TRUNC overwrites on re-run. ----
33 sys_mkdir("/tmp/sh_gate" as *u8, 0x1ed)
34 gh_writefile("/tmp/sh_gate/shgatecfg.site" as *u8, "current-config" as *u8)
35 gh_writefile("/tmp/sh_gate/shgatecfg.site.v1000" as *u8, "snapshot-1000" as *u8)
36 gh_writefile("/tmp/sh_gate/shgatecfg.site.v3000" as *u8, "snapshot-3000" as *u8) // out of order -> tests sort
37 gh_writefile("/tmp/sh_gate/shgatecfg.site.v2000" as *u8, "snapshot-2000" as *u8)
38 gh_writefile("/tmp/sh_gate/shgatecfg.site.new" as *u8, "staging-noise" as *u8) // must be EXCLUDED
39 gh_writefile("/tmp/sh_gate/shgatecfg.site.vXY" as *u8, "nondigit-noise" as *u8) // must be EXCLUDED
40 gh_writefile("/tmp/sh_gate/other.file" as *u8, "unrelated-noise" as *u8) // must be EXCLUDED
41
42 // ---- sh_match: accept <base>.v<digits>, reject every noise shape ----
43 gh_w("- sh_match\n" as *u8)
44 total = total + 1; pass = pass + gh_eq("M1 base.v1000 -> 1000" as *u8, sh_match("shgatecfg.site.v1000" as *u8, "shgatecfg.site" as *u8, 14), 1000)
45 total = total + 1; pass = pass + gh_eq("M2 base.new -> 0" as *u8, sh_match("shgatecfg.site.new" as *u8, "shgatecfg.site" as *u8, 14), 0)
46 total = total + 1; pass = pass + gh_eq("M3 bare base -> 0" as *u8, sh_match("shgatecfg.site" as *u8, "shgatecfg.site" as *u8, 14), 0)
47 total = total + 1; pass = pass + gh_eq("M4 base.vXY (nondigit) -> 0" as *u8, sh_match("shgatecfg.site.vXY" as *u8, "shgatecfg.site" as *u8, 14), 0)
48 total = total + 1; pass = pass + gh_eq("M5 base.v (empty) -> 0" as *u8, sh_match("shgatecfg.site.v" as *u8, "shgatecfg.site" as *u8, 14), 0)
49 total = total + 1; pass = pass + gh_eq("M6 base.v12x (trailing nondigit) -> 0" as *u8, sh_match("shgatecfg.site.v12x" as *u8, "shgatecfg.site" as *u8, 14), 0)
50 total = total + 1; pass = pass + gh_eq("M7 other prefix -> 0" as *u8, sh_match("other.file" as *u8, "shgatecfg.site" as *u8, 14), 0)
51
52 // ---- sh_list: exactly the 3 real snapshots, noise excluded ----
53 gh_w("- sh_list + sh_sort_desc (fixture FS)\n" as *u8)
54 let eps: *i64 = sys_mmap(8 * 64)
55 let cnt: i64 = sh_list("/tmp/sh_gate/shgatecfg.site" as *u8, eps, 64)
56 total = total + 1; pass = pass + gh_eq("L1 exactly 3 snapshots (noise excluded)" as *u8, cnt, 3)
57 sh_sort_desc(eps, cnt)
58 total = total + 1; pass = pass + gh_eq("L2 newest first [0]=3000" as *u8, eps[0], 3000)
59 total = total + 1; pass = pass + gh_eq("L3 [1]=2000" as *u8, eps[1], 2000)
60 total = total + 1; pass = pass + gh_eq("L4 oldest last [2]=1000" as *u8, eps[2], 1000)
61
62 // ---- sh_dir_of ----
63 gh_w("- sh_dir_of + sh_version_path\n" as *u8)
64 let dbuf: *u8 = sys_mmap(256)
65 let boff: i64 = sh_dir_of("/a/b/c.site" as *u8, dbuf)
66 total = total + 1; pass = pass + gh_eq("D1 basename offset" as *u8, boff, 5)
67 total = total + 1; pass = pass + gh_eq("D2 dir == /a/b" as *u8, gh_streq(dbuf, "/a/b" as *u8), 1)
68 // basename slice
69 let bn: *u8 = (("/a/b/c.site" as i64) + boff) as *u8
70 total = total + 1; pass = pass + gh_eq("D3 basename == c.site" as *u8, gh_streq(bn, "c.site" as *u8), 1)
71
72 // ---- sh_version_path ----
73 let vp: *u8 = sys_mmap(256)
74 let vpl: i64 = sh_version_path("/x/y.site" as *u8, 42, vp)
75 total = total + 1; pass = pass + gh_eq("V1 path len" as *u8, vpl, 13)
76 total = total + 1; pass = pass + gh_eq("V2 path == /x/y.site.v42" as *u8, gh_streq(vp, "/x/y.site.v42" as *u8), 1)
77
78 // ---- sh_qs_epoch: parse &v=<epoch> from a request path (must ignore a 'v' inside the s= token) ----
79 gh_w("- sh_qs_epoch\n" as *u8)
80 total = total + 1; pass = pass + gh_eq("Q1 s=tok&v=42 -> 42" as *u8, sh_qs_epoch("/site/restore?s=aVbvcv-_9&v=42" as *u8, sh_slen("/site/restore?s=aVbvcv-_9&v=42" as *u8)), 42)
81 total = total + 1; pass = pass + gh_eq("Q2 no &v= -> 0" as *u8, sh_qs_epoch("/site/restore?s=aVbvcv-_9" as *u8, sh_slen("/site/restore?s=aVbvcv-_9" as *u8)), 0)
82 total = total + 1; pass = pass + gh_eq("Q3 &v= empty -> 0" as *u8, sh_qs_epoch("/site/restore?s=t&v=" as *u8, sh_slen("/site/restore?s=t&v=" as *u8)), 0)
83 total = total + 1; pass = pass + gh_eq("Q4 &v=1700000000 big epoch" as *u8, sh_qs_epoch("/site/x?s=q&v=1700000000&z=1" as *u8, sh_slen("/site/x?s=q&v=1700000000&z=1" as *u8)), 1700000000)
84
85 gh_w("== result " as *u8); gh_wn(pass)
86 gh_w(" total=" as *u8); gh_wn(total)
87 if pass == total { gh_w("SITEEDIT_HISTORY_GATE PASS\n" as *u8); return 0 }
88 gh_w("SITEEDIT_HISTORY_GATE FAIL\n" as *u8)
89 return 1
90}