code wiki / (root) / nx_deflate_huffman_test.nx

nx_deflate_huffman_test.nx source

↩ module page · 192 lines · 7142 B

1// nx_deflate_huffman_test.nx -- regression smoke for the BTYPE=01 2// (static Huffman) and BTYPE=10 (dynamic Huffman) inflate paths. 3// 4// SURFACED 2026-05-18: nx_deflate.nx self-reports 5// "CAPABILITY_COMPLETENESS: FULL -- all three BTYPE handlers 6// (stored, static Huffman, dynamic Huffman) implemented end-to-end" 7// but only BTYPE=00 (stored) was ever exercised by an existing smoke. 8// Real PNGs from gen-img use BTYPE=01/10 and crashed the substrate. 9// This test pins the Huffman paths with python-zlib ground-truth 10// byte sequences so the false-OK can't return. 11// 12// Fixtures captured via: 13// python3 -c "import zlib; co = zlib.compressobj(level=zlib.Z_BEST_SPEED, 14// wbits=-zlib.MAX_WBITS, strategy=zlib.Z_FIXED); 15// print(co.compress(b'Hello, world!') + co.flush())" 16 17import "nx_syscalls.nx" 18import "nx_runtime.nx" 19import "nx_deflate.nx" 20 21func main() -> nx_int { 22 // ---- Test 1: BTYPE=01 static Huffman, "Hello, world!" ---- 23 // 24 // Raw DEFLATE bytes (no zlib wrapper), strategy=Z_FIXED: 25 // 0xf3 0x48 0xcd 0xc9 0xc9 0xd7 0x51 0x28 26 // 0xcf 0x2f 0xca 0x49 0x51 0x04 0x00 27 // (15 bytes encoding 13-byte "Hello, world!") 28 let static_in: *u8 = (sys_mmap(16)) as *u8 29 static_in[0] = 0xf3 as u8 30 static_in[1] = 0x48 as u8 31 static_in[2] = 0xcd as u8 32 static_in[3] = 0xc9 as u8 33 static_in[4] = 0xc9 as u8 34 static_in[5] = 0xd7 as u8 35 static_in[6] = 0x51 as u8 36 static_in[7] = 0x28 as u8 37 static_in[8] = 0xcf as u8 38 static_in[9] = 0x2f as u8 39 static_in[10] = 0xca as u8 40 static_in[11] = 0x49 as u8 41 static_in[12] = 0x51 as u8 42 static_in[13] = 0x04 as u8 43 static_in[14] = 0x00 as u8 44 45 let r_static: *NxDeflateResult = nx_deflate_inflate(static_in, 15, 64) 46 if r_static == (0 as *NxDeflateResult) { return 1 } 47 if r_static.error_code != NX_DEF_OK { return 2 } 48 if r_static.output_size != 13 { return 3 } 49 // Expected: "Hello, world!" 50 let exp_static: *u8 = (sys_mmap(16)) as *u8 51 exp_static[0] = 0x48 as u8 // 'H' 52 exp_static[1] = 0x65 as u8 // 'e' 53 exp_static[2] = 0x6c as u8 // 'l' 54 exp_static[3] = 0x6c as u8 // 'l' 55 exp_static[4] = 0x6f as u8 // 'o' 56 exp_static[5] = 0x2c as u8 // ',' 57 exp_static[6] = 0x20 as u8 // ' ' 58 exp_static[7] = 0x77 as u8 // 'w' 59 exp_static[8] = 0x6f as u8 // 'o' 60 exp_static[9] = 0x72 as u8 // 'r' 61 exp_static[10] = 0x6c as u8 // 'l' 62 exp_static[11] = 0x64 as u8 // 'd' 63 exp_static[12] = 0x21 as u8 // '!' 64 var i: nx_int = 0 65 while i < 13 { 66 let got: nx_int = (r_static.output_data[i] as nx_int) & 255 67 let want: nx_int = (exp_static[i] as nx_int) & 255 68 if got != want { 69 return 100 + i 70 } 71 i = i + 1 72 } 73 74 // ---- Test 2: BTYPE=01 static Huffman WITH BACK-REFS ---- 75 // 76 // Test 1 covered the literal-only path. Real PNGs have lots of 77 // repetition and so the deflate stream uses length/distance 78 // back-references (symbols >256 in the literal/length tree). 79 // Input "ABCABCABCABCABCABCABCABC" (24 bytes) compresses to 7 80 // bytes via Z_FIXED, forcing a back-ref to be exercised: 81 // 0x73 0x74 0x72 0x76 0xc4 0x86 0x00 82 let br_in: *u8 = (sys_mmap(8)) as *u8 83 br_in[0] = 0x73 as u8 84 br_in[1] = 0x74 as u8 85 br_in[2] = 0x72 as u8 86 br_in[3] = 0x76 as u8 87 br_in[4] = 0xc4 as u8 88 br_in[5] = 0x86 as u8 89 br_in[6] = 0x00 as u8 90 91 let r_br: *NxDeflateResult = nx_deflate_inflate(br_in, 7, 64) 92 if r_br == (0 as *NxDeflateResult) { return 200 } 93 if r_br.error_code != NX_DEF_OK { return 201 } 94 if r_br.output_size != 24 { return 202 } 95 // Expected: "ABCABCABCABCABCABCABCABC" 96 var k: nx_int = 0 97 while k < 24 { 98 let got_b: nx_int = (r_br.output_data[k] as nx_int) & 255 99 // Pattern: byte k = 'A'+(k%3) = 65, 66, 67, 65, 66, 67, ... 100 let want_b: nx_int = 65 + (k % 3) 101 if got_b != want_b { 102 return 300 + k 103 } 104 k = k + 1 105 } 106 107 // ---- Test 3: BTYPE=10 DYNAMIC Huffman (the failing-in-prod path) ---- 108 // 109 // 50x50 RGB solid-skin PNG-style scanlines compressed by zlib 110 // (level=6 default) produces a 61-byte raw DEFLATE stream that 111 // uses dynamic Huffman. Same shape as real gen-img PNG IDAT 112 // bytes. Expected uncompressed size = 50*(1 + 50*3) = 7550. 113 let dyn_in: *u8 = (sys_mmap(64)) as *u8 114 dyn_in[0] = 0xed as u8 115 dyn_in[1] = 0xce as u8 116 dyn_in[2] = 0x41 as u8 117 dyn_in[3] = 0x0d as u8 118 dyn_in[4] = 0x00 as u8 119 dyn_in[5] = 0x20 as u8 120 dyn_in[6] = 0x0c as u8 121 dyn_in[7] = 0x00 as u8 122 dyn_in[8] = 0xb1 as u8 123 dyn_in[9] = 0xf9 as u8 124 dyn_in[10] = 0x17 as u8 125 dyn_in[11] = 0x80 as u8 126 dyn_in[12] = 0x08 as u8 127 dyn_in[13] = 0x94 as u8 128 dyn_in[14] = 0x4c as u8 129 dyn_in[15] = 0x16 as u8 130 dyn_in[16] = 0x32 as u8 131 dyn_in[17] = 0xb8 as u8 132 dyn_in[18] = 0x47 as u8 133 dyn_in[19] = 0x93 as u8 134 dyn_in[20] = 0x0a as u8 135 dyn_in[21] = 0xe8 as u8 136 dyn_in[22] = 0xec as u8 137 dyn_in[23] = 0x3d as u8 138 dyn_in[24] = 0x41 as u8 139 dyn_in[25] = 0xf3 as u8 140 dyn_in[26] = 0x7d as u8 141 dyn_in[27] = 0xa0 as u8 142 dyn_in[28] = 0xa5 as u8 143 dyn_in[29] = 0xa5 as u8 144 dyn_in[30] = 0xa5 as u8 145 dyn_in[31] = 0xa5 as u8 146 dyn_in[32] = 0xa5 as u8 147 dyn_in[33] = 0xd5 as u8 148 dyn_in[34] = 0xa0 as u8 149 dyn_in[35] = 0xa5 as u8 150 dyn_in[36] = 0xa5 as u8 151 dyn_in[37] = 0x55 as u8 152 dyn_in[38] = 0xa0 as u8 153 dyn_in[39] = 0xa5 as u8 154 dyn_in[40] = 0xa5 as u8 155 dyn_in[41] = 0x55 as u8 156 dyn_in[42] = 0xa0 as u8 157 dyn_in[43] = 0xa5 as u8 158 dyn_in[44] = 0xa5 as u8 159 dyn_in[45] = 0x55 as u8 160 dyn_in[46] = 0xa0 as u8 161 dyn_in[47] = 0xa5 as u8 162 dyn_in[48] = 0xa5 as u8 163 dyn_in[49] = 0x55 as u8 164 dyn_in[50] = 0xa0 as u8 165 dyn_in[51] = 0xa5 as u8 166 dyn_in[52] = 0xa5 as u8 167 dyn_in[53] = 0x55 as u8 168 dyn_in[54] = 0xa0 as u8 169 dyn_in[55] = 0xa5 as u8 170 dyn_in[56] = 0xa5 as u8 171 dyn_in[57] = 0x55 as u8 172 dyn_in[58] = 0x10 as u8 173 dyn_in[59] = 0x6d as u8 174 dyn_in[60] = 0x3d as u8 175 176 let r_dyn: *NxDeflateResult = nx_deflate_inflate(dyn_in, 61, 8192) 177 if r_dyn == (0 as *NxDeflateResult) { return 400 } 178 if r_dyn.error_code != NX_DEF_OK { return 401 } 179 if r_dyn.output_size != 7550 { return 402 } 180 // Verify scanline structure: byte 0 = filter (0x00), byte 1 = R (0xc8), 181 // byte 2 = G (0xaa), byte 3 = B (0x96), then repeat for 50 pixels. 182 // Each scanline is 1 + 50*3 = 151 bytes. Scanline 1 starts at 151. 183 if (r_dyn.output_data[0] as nx_int) & 255 != 0x00 { return 403 } 184 if (r_dyn.output_data[1] as nx_int) & 255 != 0xc8 { return 404 } 185 if (r_dyn.output_data[2] as nx_int) & 255 != 0xaa { return 405 } 186 if (r_dyn.output_data[3] as nx_int) & 255 != 0x96 { return 406 } 187 if (r_dyn.output_data[151] as nx_int) & 255 != 0x00 { return 407 } 188 if (r_dyn.output_data[152] as nx_int) & 255 != 0xc8 { return 408 } 189 if (r_dyn.output_data[7549] as nx_int) & 255 != 0x96 { return 409 } 190 191 return 0 192}