code wiki / (root) / nx_printer_waste_test.nx

nx_printer_waste_test.nx source

↩ module page · 130 lines · 6125 B

1// nx_printer_waste_test.nx -- offline gate for the supply/waste auditor (R4). 2// Unique exit codes per invariant: 3// 1x Brother-like: BK level 0 / low 10 / high 100, duplex-capable but one-sided default 4// -> worst=EMPTY, count 1, min%=0, duplex=WASTE 5// 2x healthy 80% + duplex default -> OK, 80%, duplex=OK 6// 3x low 5% -> LOW, 5% 7// 4x 4-color KCMY {90,5,50,0} -> worst=EMPTY, count 4, min%=0 8// 5x level -1 (unknown) -> UNKNOWN, %=-1 (not a false 0%) 9// 6x no markers / no sides -> count 0 UNKNOWN, duplex=UNKNOWN 10// 7x one-sided-only printer -> duplex=UNSUPPORTED 11// expect_exit: 0 license_tier: ORIGINAL 12 13import "nx_syscalls.nx" 14import "nx_ipp_codec.nx" 15import "nx_printer_waste.nx" 16 17func t_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 18 19func base(buf: *u8) -> i64 { 20 var o: i64 = nx_ipp_begin(buf, 1, 1, NX_IPP_STATUS_OK, 1) 21 o = nx_ipp_group(buf, o, NX_IPP_GRP_PRINTER) 22 o = nx_ipp_attr_int(buf, o, NX_IPP_VT_ENUM, "printer-state", 13, NX_IPP_PSTATE_IDLE) 23 return o 24} 25 26// add sides-supported [one-sided, two-sided-long-edge, two-sided-short-edge] + sides-default. 27// def_one=1 -> default one-sided (waste); else default two-sided-long-edge. 28func add_sides(buf: *u8, off: i64, def_one: i64) -> i64 { 29 var o: i64 = off 30 let SS: *u8 = "sides-supported" 31 o = nx_ipp_attr(buf, o, NX_IPP_VT_KEYWORD, SS, nx_ipp_strlen(SS), "one-sided", 9) 32 o = nx_ipp_attr_add(buf, o, NX_IPP_VT_KEYWORD, "two-sided-long-edge", 19) 33 o = nx_ipp_attr_add(buf, o, NX_IPP_VT_KEYWORD, "two-sided-short-edge", 20) 34 let SD: *u8 = "sides-default" 35 if def_one == 1 { o = nx_ipp_attr(buf, o, NX_IPP_VT_KEYWORD, SD, nx_ipp_strlen(SD), "one-sided", 9) } 36 else { o = nx_ipp_attr(buf, o, NX_IPP_VT_KEYWORD, SD, nx_ipp_strlen(SD), "two-sided-long-edge", 19) } 37 return o 38} 39 40func main() -> i64 { 41 let sc: *i64 = sys_mmap(64) as *i64 42 let cnt: *i64 = sys_mmap(16) as *i64 43 let pct: *i64 = sys_mmap(16) as *i64 44 let dup: *i64 = sys_mmap(16) as *i64 45 let ML: *u8 = "marker-levels" 46 let MLO: *u8 = "marker-low-levels" 47 let MHI: *u8 = "marker-high-levels" 48 49 // ===== KAT 1: Brother-like (BK 0/10/100, duplex but one-sided default) ===== 50 let a: *u8 = sys_mmap(2048) 51 var oa: i64 = base(a) 52 oa = nx_ipp_attr_int(a, oa, NX_IPP_VT_INTEGER, ML, nx_ipp_strlen(ML), 0) 53 oa = nx_ipp_attr_int(a, oa, NX_IPP_VT_INTEGER, MLO, nx_ipp_strlen(MLO), 10) 54 oa = nx_ipp_attr_int(a, oa, NX_IPP_VT_INTEGER, MHI, nx_ipp_strlen(MHI), 100) 55 oa = add_sides(a, oa, 1) 56 oa = nx_ipp_end(a, oa) 57 if nx_printer_waste(a, oa, sc, cnt, pct, dup) != NX_SUP_EMPTY { return 1 } 58 if cnt[0] != 1 { return 2 } 59 if pct[0] != 0 { return 3 } 60 if dup[0] != NX_DUP_WASTE { return 4 } 61 62 // ===== KAT 2: healthy 80% + duplex default ===== 63 let b: *u8 = sys_mmap(2048) 64 var ob: i64 = base(b) 65 ob = nx_ipp_attr_int(b, ob, NX_IPP_VT_INTEGER, ML, nx_ipp_strlen(ML), 80) 66 ob = nx_ipp_attr_int(b, ob, NX_IPP_VT_INTEGER, MLO, nx_ipp_strlen(MLO), 10) 67 ob = nx_ipp_attr_int(b, ob, NX_IPP_VT_INTEGER, MHI, nx_ipp_strlen(MHI), 100) 68 ob = add_sides(b, ob, 0) 69 ob = nx_ipp_end(b, ob) 70 if nx_printer_waste(b, ob, sc, cnt, pct, dup) != NX_SUP_OK { return 10 } 71 if pct[0] != 80 { return 11 } 72 if dup[0] != NX_DUP_OK { return 12 } 73 74 // ===== KAT 3: low 5% ===== 75 let c: *u8 = sys_mmap(2048) 76 var oc: i64 = base(c) 77 oc = nx_ipp_attr_int(c, oc, NX_IPP_VT_INTEGER, ML, nx_ipp_strlen(ML), 5) 78 oc = nx_ipp_attr_int(c, oc, NX_IPP_VT_INTEGER, MLO, nx_ipp_strlen(MLO), 10) 79 oc = nx_ipp_attr_int(c, oc, NX_IPP_VT_INTEGER, MHI, nx_ipp_strlen(MHI), 100) 80 oc = nx_ipp_end(c, oc) 81 if nx_printer_waste(c, oc, sc, cnt, pct, dup) != NX_SUP_LOW { return 20 } 82 if pct[0] != 5 { return 21 } 83 84 // ===== KAT 4: 4-color KCMY {90,5,50,0} ===== 85 let d: *u8 = sys_mmap(2048) 86 var od: i64 = base(d) 87 od = nx_ipp_attr_int(d, od, NX_IPP_VT_INTEGER, ML, nx_ipp_strlen(ML), 90) 88 od = nx_ipp_attr_add_int(d, od, NX_IPP_VT_INTEGER, 5) 89 od = nx_ipp_attr_add_int(d, od, NX_IPP_VT_INTEGER, 50) 90 od = nx_ipp_attr_add_int(d, od, NX_IPP_VT_INTEGER, 0) 91 od = nx_ipp_attr_int(d, od, NX_IPP_VT_INTEGER, MLO, nx_ipp_strlen(MLO), 10) 92 od = nx_ipp_attr_add_int(d, od, NX_IPP_VT_INTEGER, 10) 93 od = nx_ipp_attr_add_int(d, od, NX_IPP_VT_INTEGER, 10) 94 od = nx_ipp_attr_add_int(d, od, NX_IPP_VT_INTEGER, 10) 95 od = nx_ipp_attr_int(d, od, NX_IPP_VT_INTEGER, MHI, nx_ipp_strlen(MHI), 100) 96 od = nx_ipp_attr_add_int(d, od, NX_IPP_VT_INTEGER, 100) 97 od = nx_ipp_attr_add_int(d, od, NX_IPP_VT_INTEGER, 100) 98 od = nx_ipp_attr_add_int(d, od, NX_IPP_VT_INTEGER, 100) 99 od = nx_ipp_end(d, od) 100 if nx_printer_waste(d, od, sc, cnt, pct, dup) != NX_SUP_EMPTY { return 30 } 101 if cnt[0] != 4 { return 31 } 102 if pct[0] != 0 { return 32 } 103 104 // ===== KAT 5: unknown level -1 -> not a false 0% ===== 105 let e: *u8 = sys_mmap(2048) 106 var oe: i64 = base(e) 107 oe = nx_ipp_attr_int(e, oe, NX_IPP_VT_INTEGER, ML, nx_ipp_strlen(ML), 0 - 1) 108 oe = nx_ipp_end(e, oe) 109 if nx_printer_waste(e, oe, sc, cnt, pct, dup) != NX_SUP_UNKNOWN { return 40 } 110 if cnt[0] != 1 { return 41 } 111 if pct[0] != (0 - 1) { return 42 } 112 113 // ===== KAT 6: no markers, no sides ===== 114 let f: *u8 = sys_mmap(2048) 115 var of: i64 = base(f) 116 of = nx_ipp_end(f, of) 117 if nx_printer_waste(f, of, sc, cnt, pct, dup) != NX_SUP_UNKNOWN { return 50 } 118 if cnt[0] != 0 { return 51 } 119 if dup[0] != NX_DUP_UNKNOWN { return 52 } 120 121 // ===== KAT 7: one-sided-only printer -> duplex unsupported ===== 122 let g: *u8 = sys_mmap(2048) 123 var og: i64 = base(g) 124 og = nx_ipp_attr(g, og, NX_IPP_VT_KEYWORD, "sides-supported", 15, "one-sided", 9) 125 og = nx_ipp_end(g, og) 126 if nx_pw_duplex(g, og) != NX_DUP_UNSUPPORTED { return 60 } 127 128 t_puts("nx_printer_waste: 7/7 KAT groups PASS (supply OK/LOW/EMPTY/UNKNOWN + multi-supply + duplex-waste/unsupported)\n") 129 return 0 130}