CRC checksums (CRC-16, CRC-32, CRC-32C) for OCaml
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Strengthen CRC tests: residue, boundary, hw/sw agreement

- Add CRC-32C single byte "A" test (0xE16DCDEE, RevEng catalogue)
- Add CRC-32 and CRC-32C residue tests: verify that CRC(data || LE(CRC))
yields the expected constant (residue XOR xorout per RevEng)
- Add slicing-by-8 boundary tests at 1,7,8,9,15,16,17,31-65 bytes
to stress the 8-byte bulk loop and tail
- Add fuzz tests for hardware vs software agreement on CRC-32 and CRC-32C

+58
+10
fuzz/fuzz_crc.ml
··· 61 61 let test_crc32c_deterministic s = 62 62 check_eq ~pp:Format.pp_print_int (Crc.crc32c s) (Crc.crc32c s) 63 63 64 + (* CRC-32: hardware and software agree *) 65 + let test_crc32_hw_sw_agree s = 66 + check_eq ~pp:Format.pp_print_int (Crc.crc32 s) (Crc.crc32_software s) 67 + 68 + (* CRC-32C: hardware and software agree *) 69 + let test_crc32c_hw_sw_agree s = 70 + check_eq ~pp:Format.pp_print_int (Crc.crc32c s) (Crc.crc32c_software s) 71 + 64 72 let suite = 65 73 ( "crc", 66 74 [ ··· 73 81 test_case "32-bit range (crc32c)" [ bytes ] test_crc32c_32bit; 74 82 test_case "deterministic (ccitt)" [ bytes ] test_ccitt_deterministic; 75 83 test_case "deterministic (crc32c)" [ bytes ] test_crc32c_deterministic; 84 + test_case "hw=sw (crc32)" [ bytes ] test_crc32_hw_sw_agree; 85 + test_case "hw=sw (crc32c)" [ bytes ] test_crc32c_hw_sw_agree; 76 86 ] )
+48
test/test_crc.ml
··· 84 84 check "RFC 3720 check value" 0xE3069283 (Crc.crc32c check_string) 85 85 86 86 let test_crc32c_empty () = check "empty input" 0 (Crc.crc32c "") 87 + let test_crc32c_single () = check "single byte 0x41" 0xE16DCDEE (Crc.crc32c "A") 87 88 88 89 let test_crc32c_bytes () = 89 90 let buf = Bytes.of_string ("xx" ^ check_string ^ "zz") in ··· 111 112 let data = String.init 32 (fun i -> Char.chr (31 - i)) in 112 113 check "RFC 3720: descending bytes" 0x113FDB5C (Crc.crc32c data) 113 114 115 + (* {1 CRC-32 residue test} 116 + 117 + For reflected CRC, appending the CRC little-endian yields a constant. 118 + RevEng catalogue: CRC-32/ISO-HDLC residue=0xdebb20e3 (pre-XOR). 119 + Our function applies xorout=0xFFFFFFFF, so the observed constant is 120 + residue XOR xorout = 0xDEBB20E3 XOR 0xFFFFFFFF = 0x2144DF1C. *) 121 + 122 + let test_crc32_residue () = 123 + let data = "Hello, CRC!" in 124 + let crc = Crc.crc32 data in 125 + let with_crc = 126 + data ^ String.init 4 (fun i -> Char.chr ((crc lsr (i * 8)) land 0xFF)) 127 + in 128 + check "CRC-32 residue" 0x2144DF1C (Crc.crc32 with_crc) 129 + 130 + (* {1 CRC-32C residue test} 131 + 132 + RevEng catalogue: CRC-32/ISCSI residue=0xb798b438 (pre-XOR). 133 + Observed: 0xB798B438 XOR 0xFFFFFFFF = 0x48674BC7. *) 134 + 135 + let test_crc32c_residue () = 136 + let data = "Hello, CRC!" in 137 + let crc = Crc.crc32c data in 138 + let with_crc = 139 + data ^ String.init 4 (fun i -> Char.chr ((crc lsr (i * 8)) land 0xFF)) 140 + in 141 + check "CRC-32C residue" 0x48674BC7 (Crc.crc32c with_crc) 142 + 143 + (* {1 Slicing-by-8 boundary tests} 144 + 145 + The slicing-by-8 loop processes 8 bytes per iteration. These tests 146 + exercise lengths at and around the 8-byte boundary to stress the 147 + transition between the bulk loop and the byte-at-a-time tail. *) 148 + 149 + let test_crc32c_boundary () = 150 + let check_len n = 151 + let data = String.init n (fun i -> Char.chr (i land 0xFF)) in 152 + let hw = Crc.crc32c data in 153 + let sw = Crc.crc32c_software data in 154 + check (Printf.sprintf "%d bytes: hw=sw" n) sw hw 155 + in 156 + List.iter check_len [ 1; 7; 8; 9; 15; 16; 17; 31; 32; 33; 63; 64; 65 ] 157 + 114 158 let suite = 115 159 ( "crc", 116 160 [ ··· 128 172 Alcotest.test_case "crc32: single byte" `Quick test_crc32_single; 129 173 Alcotest.test_case "crc32c: RFC 3720 check" `Quick test_crc32c_check; 130 174 Alcotest.test_case "crc32c: empty" `Quick test_crc32c_empty; 175 + Alcotest.test_case "crc32c: single byte" `Quick test_crc32c_single; 131 176 Alcotest.test_case "crc32c: bytes sub-range" `Quick test_crc32c_bytes; 132 177 Alcotest.test_case "crc32c: RFC 3720: 32 zeros" `Quick 133 178 test_crc32c_rfc3720_zeros; ··· 137 182 test_crc32c_rfc3720_ascending; 138 183 Alcotest.test_case "crc32c: RFC 3720: descending" `Quick 139 184 test_crc32c_rfc3720_descending; 185 + Alcotest.test_case "crc32: residue" `Quick test_crc32_residue; 186 + Alcotest.test_case "crc32c: residue" `Quick test_crc32c_residue; 187 + Alcotest.test_case "crc32c: slicing boundary" `Quick test_crc32c_boundary; 140 188 ] )