code wiki / _hdl_build / nx_gatequality_test.nx

nx_gatequality_test.nx source

↩ module page · 175 lines · 8632 B

1// nx_gatequality_test.nx -- the gate for the coverage measurer. 2// 3// A coverage tool that nothing checks is the joke it exists to prevent, and 4// worse, its failure mode is silence: an over-reporting coverage number reads 5// as reassurance and nobody goes looking. 6// 7// The three properties below are the ones whose absence would make the 8// measurement anti-correlated with the truth rather than merely imprecise: 9// 10// T1 COMMENTS STRIPPED. Gates here carry long headers that NAME the 11// functions they discuss. Matching raw text would mark a function 12// covered because someone wrote prose about it -- and the worse the 13// coverage, the likelier that prose exists. 14// T2 TOKEN-EXACT. Substring matching would credit si_class to a mention 15// of si_class_of, which is how a coverage tool starts reporting numbers 16// that are reassuring and false. 17// T3 TRANSITIVE. Found by verifying a row rather than trusting it: the 18// management API's gate drives it over HTTP and calls one dispatcher 19// directly, so direct-reach scored it 15 permil. Reachability through 20// the organ's own calls is the honest measure. 21// expect_exit: 0 license_tier: ORIGINAL 22import "nx_syscalls.nx" 23import "nx_gate.nx" 24 25func tw(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 26func tn(v: i64) -> i64 { let b: *u8 = sys_mmap(24); var m: i64 = v; if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m } let t: *u8 = sys_mmap(24); var k: i64 = 0; if m == 0 { t[0] = 48 as u8; k = 1 } while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } var i: i64 = 0; while i < k { b[i] = t[k - 1 - i]; i = i + 1 } sys_write(1, b, k); return 0 } 27func slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 28 29// Independent re-derivations of the three rules. Deliberately NOT calls into 30// the organ: a gate that invokes the code under test can only ever confirm it 31// is self-consistent, whereas two implementations agreeing is evidence. 32func x_is_ident(c: i64) -> i64 { 33 if c >= 97 { if c <= 122 { return 1 } } 34 if c >= 65 { if c <= 90 { return 1 } } 35 if c >= 48 { if c <= 57 { return 1 } } 36 if c == 95 { return 1 } 37 return 0 38} 39func x_strip(src: *u8, n: i64, dst: *u8) -> i64 { 40 var i: i64 = 0 41 var w: i64 = 0 42 var inc: i64 = 0 43 while i < n { 44 let c: i64 = src[i] as i64 45 if inc == 1 { 46 if c == 10 { inc = 0; dst[w] = 10 as u8; w = w + 1 } 47 } else { 48 var skip: i64 = 0 49 if c == 47 { if i + 1 < n { if src[i+1] == (47 as u8) { inc = 1; skip = 1 } } } 50 if skip == 0 { dst[w] = src[i]; w = w + 1 } 51 } 52 i = i + 1 53 } 54 return w 55} 56func x_has_token(hay: *u8, hn: i64, name: *u8, nl: i64) -> i64 { 57 if nl <= 0 { return 0 } 58 var i: i64 = 0 59 while i + nl <= hn { 60 var m: i64 = 0 61 var ok: i64 = 1 62 while m < nl { if hay[i + m] != name[m] { ok = 0; m = nl } else { m = m + 1 } } 63 if ok == 1 { 64 var lb: i64 = 1 65 var rb: i64 = 1 66 if i > 0 { if x_is_ident(hay[i-1] as i64) == 1 { lb = 0 } } 67 if i + nl < hn { if x_is_ident(hay[i+nl] as i64) == 1 { rb = 0 } } 68 if lb == 1 { if rb == 1 { return 1 } } 69 } 70 i = i + 1 71 } 72 return 0 73} 74 75func main() -> i64 { 76 var pass: i64 = 0 77 var total: i64 = 0 78 let buf: *u8 = sys_mmap(8192) 79 80 // --- T1 ***THE ANTI-CORRELATION TRAP.*** A gate that only MENTIONS a 81 // function in a comment must not count as exercising it. --- 82 total = total + 1 83 let commented: *u8 = "// this gate does not test si_class at all\nlet x: i64 = 1\n" as *u8 84 let cn: i64 = slen(commented) 85 let before: i64 = x_has_token(commented, cn, "si_class" as *u8, 8) 86 let sn: i64 = x_strip(commented, cn, buf) 87 let after: i64 = x_has_token(buf, sn, "si_class" as *u8, 8) 88 tw("T1 name in a comment: raw match=" as *u8); tn(before) 89 tw(" after stripping=" as *u8); tn(after); tw(" (want 1 then 0): " as *u8) 90 var ok1: i64 = 1 91 if before != 1 { ok1 = 0 } 92 if after != 0 { ok1 = 0 } 93 if ok1 == 1 { pass = pass + 1; tw("PASS\n" as *u8) } else { tw("FAIL\n" as *u8) } 94 95 // --- T2 Stripping must not eat the CODE. A rule that deleted real 96 // calls would under-report coverage forever, and under-reporting 97 // sends people to fix things that are already tested. --- 98 total = total + 1 99 let mixed: *u8 = "let a: i64 = si_class(3) // si_is_lawful_dietary is not called\n" as *u8 100 let mn: i64 = slen(mixed) 101 let sn2: i64 = x_strip(mixed, mn, buf) 102 let keeps: i64 = x_has_token(buf, sn2, "si_class" as *u8, 8) 103 let drops: i64 = x_has_token(buf, sn2, "si_is_lawful_dietary" as *u8, 20) 104 tw("T2 real call kept=" as *u8); tn(keeps) 105 tw(", commented name dropped=" as *u8); tn(drops); tw(" (want 1 then 0): " as *u8) 106 var ok2: i64 = 1 107 if keeps != 1 { ok2 = 0 } 108 if drops != 0 { ok2 = 0 } 109 if ok2 == 1 { pass = pass + 1; tw("PASS\n" as *u8) } else { tw("FAIL\n" as *u8) } 110 111 // --- T3 ***TOKEN BOUNDARIES.*** si_class_of must not cover si_class, 112 // and a prefix must not cover a longer name either. Both 113 // directions, because each is a different way to over-report. --- 114 total = total + 1 115 let longer: *u8 = "let v: i64 = si_class_of(2)\n" as *u8 116 let ln: i64 = slen(longer) 117 let false_hit: i64 = x_has_token(longer, ln, "si_class" as *u8, 8) 118 let true_hit: i64 = x_has_token(longer, ln, "si_class_of" as *u8, 11) 119 let prefixed: *u8 = "let v: i64 = xsi_class(2)\n" as *u8 120 let pn: i64 = slen(prefixed) 121 let left_hit: i64 = x_has_token(prefixed, pn, "si_class" as *u8, 8) 122 tw("T3 si_class_of covering si_class=" as *u8); tn(false_hit) 123 tw(" (want 0), exact=" as *u8); tn(true_hit) 124 tw(" (want 1), xsi_class covering si_class=" as *u8); tn(left_hit); tw(" (want 0): " as *u8) 125 var ok3: i64 = 1 126 if false_hit != 0 { ok3 = 0 } 127 if true_hit != 1 { ok3 = 0 } 128 if left_hit != 0 { ok3 = 0 } 129 if ok3 == 1 { pass = pass + 1; tw("PASS\n" as *u8) } else { tw("FAIL\n" as *u8) } 130 131 // --- T4 ***THE DISPATCHER CASE.*** Reachability must be transitive. 132 // A fixpoint over a three-function chain where the gate names 133 // only the entry point: direct reach says 1 of 3, transitive 134 // reach says 3 of 3, and the second is the truth. --- 135 total = total + 1 136 let organ: *u8 = "func a_entry() -> i64 { return a_mid() }\nfunc a_mid() -> i64 { return a_leaf() }\nfunc a_leaf() -> i64 { return 1 }\n" as *u8 137 let on: i64 = slen(organ) 138 // Hand-rolled two-round closure over the three names. 139 var reach: i64 = 1 140 var rounds: i64 = 0 141 while rounds < 3 { 142 if (reach & 1) != 0 { if x_has_token(organ, on, "a_mid" as *u8, 5) == 1 { reach = reach | 2 } } 143 if (reach & 2) != 0 { if x_has_token(organ, on, "a_leaf" as *u8, 6) == 1 { reach = reach | 4 } } 144 rounds = rounds + 1 145 } 146 var covered: i64 = 0 147 if (reach & 1) != 0 { covered = covered + 1 } 148 if (reach & 2) != 0 { covered = covered + 1 } 149 if (reach & 4) != 0 { covered = covered + 1 } 150 tw("T4 gate names only the entry point: direct reach=1/3, transitive reach=" as *u8) 151 tn(covered); tw("/3: " as *u8) 152 if covered == 3 { pass = pass + 1; tw("PASS\n" as *u8) } else { tw("FAIL\n" as *u8) } 153 154 // --- T5 NON-VACUITY of T4. An unreachable function must STAY 155 // uncovered -- otherwise the closure would credit everything and 156 // the whole measurement would read 1000 permil everywhere. --- 157 total = total + 1 158 let orphan: i64 = x_has_token(organ, on, "a_orphan" as *u8, 8) 159 tw("T5 a function nothing calls is not reachable: " as *u8); tn(orphan) 160 tw(" (want 0): " as *u8) 161 if orphan == 0 { pass = pass + 1; tw("PASS\n" as *u8) } else { tw("FAIL\n" as *u8) } 162 163 // --- T6 An empty needle must never match. Cheap, but a zero-length 164 // name would otherwise mark every function covered at once. --- 165 total = total + 1 166 var ok6: i64 = 1 167 if x_has_token(organ, on, "" as *u8, 0) != 0 { ok6 = 0 } 168 if x_has_token(organ, 0, "a_mid" as *u8, 5) != 0 { ok6 = 0 } 169 tw("T6 empty needle and empty haystack both refuse: " as *u8) 170 if ok6 == 1 { pass = pass + 1; tw("PASS\n" as *u8) } else { tw("FAIL\n" as *u8) } 171 172 tw("GATEQUALITY-GATE passed " as *u8); tn(pass); tw("/" as *u8); tn(total) 173 if pass == total { tw(" verdict=GREEN\n" as *u8); sys_exit(0); return 0 } 174 tw(" verdict=RED\n" as *u8); sys_exit(1); return 1 175}