code wiki / _hdl_build / nx_adnet_billv_gate.nx
nx_adnet_billv_gate.nx source
↩ module page · 104 lines · 6609 B
1// nx_adnet_billv_gate.nx -- GATE for viewable-basis billing (nx_adnet_bill anb_invoice_line_v).
2// The decisive teeth are the ones a regression trips FIRST, and each is chosen so pass and fail produce
3// DIFFERENT DIGITS (500 vs 5000) -- a tooth whose two outcomes look alike proves nothing:
4// (1) BASIS: served=1000 viewable=100 must bill 100's worth. Billing 1000's worth means the basis
5// silently reverted to the served journal, which is the whole defect (1785512185).
6// (2) ANTI-FALLBACK: viewable UNMEASURED must REFUSE and must NOT contain the served-basis figure.
7// (3) ANTI-FORGERY: viewable > served must REFUSE. The /ad/view beacon is unauthenticated and its url
8// is printed in every page's source, so the count is forgeable; a creative cannot be seen more
9// times than it was sent, so that pair is BROKEN, not merely large.
10// expect_exit: 0 license_tier: ORIGINAL
11import "nx_syscalls.nx"
12import "_hdl_build/nx_adnet_bill.nx"
13import "nx_gate_verdict.nx"
14
15func tb_slen(s: *u8) -> i64 { var i: i64 = 0; while s[i] != (0 as u8) { i = i + 1 } return i }
16func tb_puts(s: *u8) -> i64 { sys_write(1, s, tb_slen(s)); return 0 }
17func tb_pn(v: i64) -> i64 {
18 let b: *u8 = sys_mmap(32)
19 if v == 0 { b[0] = 48 as u8; sys_write(1, b, 1); return 0 }
20 var n: i64 = 0
21 var x: i64 = v
22 while x > 0 { b[n] = ((x - (x / 10) * 10) + 48) as u8; n = n + 1; x = x / 10 }
23 let r: *u8 = sys_mmap(32)
24 var i: i64 = 0
25 while i < n { r[i] = b[n - 1 - i]; i = i + 1 }
26 sys_write(1, r, n)
27 return 0
28}
29func tb_has(buf: *u8, n: i64, pat: *u8) -> i64 {
30 let pl: i64 = tb_slen(pat)
31 if pl == 0 { return 0 }
32 if pl > n { return 0 }
33 var i: i64 = 0
34 while i <= n - pl {
35 var k: i64 = 0
36 var ok: i64 = 1
37 while k < pl { if buf[i + k] != pat[k] { ok = 0; break } k = k + 1 }
38 if ok == 1 { return 1 }
39 i = i + 1
40 }
41 return 0
42}
43func tb_check(name: *u8, cond: i64) -> i64 {
44 if cond == 1 { tb_puts(" PASS " as *u8) } else { tb_puts(" FAIL " as *u8) }
45 tb_puts(name); tb_puts("\n" as *u8)
46 return cond
47}
48
49func main() -> i64 {
50 tb_puts("=== nx_adnet_billv_gate ===\n" as *u8)
51 var pass: i64 = 0
52 var total: i64 = 0
53 let buf: *u8 = sys_mmap(4096)
54
55 // ---- (1) BASIS ----
56 let n1: i64 = anb_invoice_line_v("ha-video" as *u8, 1000, 100, 0, 5000, 0, 0 - 1, buf, 4096)
57 pass = pass + tb_check("line emitted" as *u8, n1 > 0); total = total + 1
58 pass = pass + tb_check("basis is declared viewable" as *u8, tb_has(buf, n1, "basis=viewable" as *u8)); total = total + 1
59 pass = pass + tb_check("bills the VIEWABLE figure (due_milli=500)" as *u8, tb_has(buf, n1, "due_milli=500" as *u8)); total = total + 1
60 pass = pass + tb_check("does NOT bill the served figure (5000 absent)" as *u8, tb_has(buf, n1, "due_milli=5000" as *u8) == 0); total = total + 1
61 pass = pass + tb_check("served count still reported" as *u8, tb_has(buf, n1, "served=1000" as *u8)); total = total + 1
62 pass = pass + tb_check("viewable count reported" as *u8, tb_has(buf, n1, "viewable=100" as *u8)); total = total + 1
63 pass = pass + tb_check("delivery ratio 100 permille" as *u8, tb_has(buf, n1, "deliv_permille=100" as *u8)); total = total + 1
64
65 // ---- (2) ANTI-FALLBACK ----
66 let n2: i64 = anb_invoice_line_v("ha-video" as *u8, 1000, 0 - 1, 0, 5000, 0, 0 - 1, buf, 4096)
67 pass = pass + tb_check("unmeasured viewable -> labelled UNMEASURED" as *u8, tb_has(buf, n2, "viewable=UNMEASURED" as *u8)); total = total + 1
68 pass = pass + tb_check("unmeasured viewable -> due REFUSED" as *u8, tb_has(buf, n2, "due_milli=REFUSED" as *u8)); total = total + 1
69 pass = pass + tb_check("unmeasured viewable -> NO served fallback (5000 absent)" as *u8, tb_has(buf, n2, "5000" as *u8) == 0); total = total + 1
70 pass = pass + tb_check("unmeasured viewable -> ratio REFUSED" as *u8, tb_has(buf, n2, "deliv_permille=REFUSED" as *u8)); total = total + 1
71
72 // ---- (3) ANTI-FORGERY: the beacon is unauthenticated, so this pair must never bill ----
73 let n6: i64 = anb_invoice_line_v("ha-video" as *u8, 10, 99, 0, 5000, 0, 0 - 1, buf, 4096)
74 pass = pass + tb_check("viewable > served -> due REFUSED (forged beacon cannot bill)" as *u8, tb_has(buf, n6, "due_milli=REFUSED" as *u8)); total = total + 1
75 pass = pass + tb_check("viewable > served -> ratio REFUSED" as *u8, tb_has(buf, n6, "deliv_permille=REFUSED" as *u8)); total = total + 1
76 pass = pass + tb_check("viewable > served -> names the reason" as *u8, tb_has(buf, n6, "reason=viewable-exceeds-served" as *u8)); total = total + 1
77 pass = pass + tb_check("viewable == served is LEGAL (perfect delivery bills)" as *u8, anb_deliv_permille(10, 10) == 1000); total = total + 1
78
79 // ---- ratio grounding ----
80 pass = pass + tb_check("served=0 -> ratio REFUSED" as *u8, anb_deliv_permille(0, 0) == 0 - 1); total = total + 1
81 pass = pass + tb_check("negative served -> ratio REFUSED" as *u8, anb_deliv_permille(0 - 1, 10) == 0 - 1); total = total + 1
82 pass = pass + tb_check("ratio math: 250/1000 = 250 permille" as *u8, anb_deliv_permille(1000, 250) == 250); total = total + 1
83
84 // ---- cap and clicks still honoured ----
85 let n3: i64 = anb_invoice_line_v("ha-video" as *u8, 1000, 100, 3, 5000, 100, 0 - 1, buf, 4096)
86 pass = pass + tb_check("clicks billed on top (500 + 300 = 800)" as *u8, tb_has(buf, n3, "due_milli=800" as *u8)); total = total + 1
87 let n4: i64 = anb_invoice_line_v("ha-video" as *u8, 1000, 100, 3, 5000, 100, 600, buf, 4096)
88 pass = pass + tb_check("period cap clamps the bill (cap 600)" as *u8, tb_has(buf, n4, "due_milli=600" as *u8)); total = total + 1
89
90 // ---- DO-NO-HARM ----
91 let n5: i64 = anb_invoice_line("ha-video" as *u8, 1000, 0, 5000, 0, 0 - 1, buf, 4096)
92 pass = pass + tb_check("legacy anb_invoice_line unchanged (imps=1000 due 5000)" as *u8, tb_has(buf, n5, "due_milli=5000" as *u8)); total = total + 1
93
94 tb_puts("pass=" as *u8); tb_pn(pass); tb_puts(" fail=" as *u8); tb_pn(total - pass); tb_puts("\n" as *u8)
95 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check
96 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled
97 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify.
98 let ctr__dry: *i64 = gv_ctr()
99 ctr__dry[0] = pass
100 ctr__dry[1] = total
101 let rc__dry: i64 = gv_verdict("ADNET-BILLV-GATE" as *u8, ctr__dry, "teeth unchanged; verdict emission migrated onto the shared base class" as *u8)
102 sys_exit(rc__dry)
103 return rc__dry
104}