oxedyne/fe2o3/fe2o3_graphics/src/qr/tests.rs
14.6 KiB, 4 runs
created by r1870400018:14234, which is this file's identity for as long as the history lasts, whatever it is later renamed to
download · who wrote it · its history
| 1 | //! Correctness tests for the QR encoder. |
| 2 | //! |
| 3 | //! The golden matrices below were produced by Project Nayuki's own `qrcodegen` crate (version 1.8) |
| 4 | //! via its `QrCode::encode_binary`, which forces byte mode and, like this encoder, boosts the |
| 5 | //! error-correction level to fill spare capacity. They serve as an external oracle: a matching |
| 6 | //! grid means the whole pipeline (segment packing, Reed-Solomon, block interleaving, function |
| 7 | //! patterns, and mask selection) agrees with an independent, widely used implementation of the |
| 8 | //! same frozen standard, not merely with itself. |
| 9 | //! |
| 10 | //! [Written with AI entirely](https://need2know.ai/entirely-ai/code)\ |
| 11 | //! Anthropic Claude |
| 12 | |
| 13 | use super::*; |
| 14 | |
| 15 | /// Renders a matrix as rows of `0` and `1` so it can be compared against a golden literal. |
| 16 | fn rows_of(qr: &QrMatrix) -> String { |
| 17 | let mut s = String::new(); |
| 18 | for y in 0 .. qr.size() { |
| 19 | for x in 0 .. qr.size() { |
| 20 | s.push(if qr.get(x, y) { '1' } else { '0' }); |
| 21 | } |
| 22 | if y + 1 < qr.size() { |
| 23 | s.push('\n'); |
| 24 | } |
| 25 | } |
| 26 | s |
| 27 | } |
| 28 | |
| 29 | fn check(text: &str, ecc: QrEcc, ver: u8, size: usize, golden: &str) { |
| 30 | let qr = match encode(text, ecc) { |
| 31 | Ok(q) => q, |
| 32 | Err(e) => panic!("encode failed: {:?}", e), |
| 33 | }; |
| 34 | assert_eq!(qr.version(), ver, "version mismatch"); |
| 35 | assert_eq!(qr.size(), size, "size mismatch"); |
| 36 | assert_eq!(rows_of(&qr), golden.trim(), "matrix mismatch"); |
| 37 | } |
| 38 | |
| 39 | #[test] |
| 40 | fn matches_oracle_hello_byte_low_00() { |
| 41 | check("HELLO WORLD", QrEcc::Low, 1, 21, HELLO_BYTE_LOW); |
| 42 | } |
| 43 | |
| 44 | #[test] |
| 45 | fn matches_oracle_url_medium_01() { |
| 46 | check("https://example.org", QrEcc::Medium, 2, 25, URL_MEDIUM); |
| 47 | } |
| 48 | |
| 49 | #[test] |
| 50 | fn matches_oracle_pair_quartile_02() { |
| 51 | check("https://daimond.app/pair?k=AbCdEf0123", QrEcc::Quartile, 4, 33, PAIR_QUARTILE); |
| 52 | } |
| 53 | |
| 54 | #[test] |
| 55 | fn matches_oracle_long_high_03() { |
| 56 | let text = "x".repeat(120); |
| 57 | check(&text, QrEcc::High, 11, 61, LONG_HIGH); |
| 58 | } |
| 59 | |
| 60 | #[test] |
| 61 | fn matches_oracle_version7plus_04() { |
| 62 | // Beyond version 6 the version-information blocks appear, so this exercises that path too. |
| 63 | let text = "y".repeat(300); |
| 64 | check(&text, QrEcc::Low, 11, 61, VER7PLUS); |
| 65 | } |
| 66 | |
| 67 | #[test] |
| 68 | fn finder_patterns_land_in_the_corners_05() { |
| 69 | let qr = match encode("finder", QrEcc::Medium) { |
| 70 | Ok(q) => q, |
| 71 | Err(e) => panic!("encode failed: {:?}", e), |
| 72 | }; |
| 73 | let n = qr.size(); |
| 74 | // Each finder is a 7 by 7 block: a dark ring, a light ring, then a dark 3 by 3 core. |
| 75 | for &(ox, oy) in &[(0usize, 0usize), (n - 7, 0), (0, n - 7)] { |
| 76 | for dy in 0 .. 7 { |
| 77 | for dx in 0 .. 7 { |
| 78 | let ring = dx == 0 || dx == 6 || dy == 0 || dy == 6; |
| 79 | let core = (2 ..= 4).contains(&dx) && (2 ..= 4).contains(&dy); |
| 80 | let expect = ring || core; |
| 81 | assert_eq!( |
| 82 | qr.get(ox + dx, oy + dy), expect, |
| 83 | "finder at ({},{}) cell ({},{})", ox, oy, dx, dy, |
| 84 | ); |
| 85 | } |
| 86 | } |
| 87 | } |
| 88 | } |
| 89 | |
| 90 | #[test] |
| 91 | fn timing_patterns_alternate_06() { |
| 92 | let qr = match encode("timing", QrEcc::Medium) { |
| 93 | Ok(q) => q, |
| 94 | Err(e) => panic!("encode failed: {:?}", e), |
| 95 | }; |
| 96 | let n = qr.size(); |
| 97 | // Row six and column six alternate dark and light between the finder separators. |
| 98 | for i in 8 .. n - 8 { |
| 99 | let expect = i % 2 == 0; |
| 100 | assert_eq!(qr.get(i, 6), expect, "horizontal timing at {}", i); |
| 101 | assert_eq!(qr.get(6, i), expect, "vertical timing at {}", i); |
| 102 | } |
| 103 | } |
| 104 | |
| 105 | #[test] |
| 106 | fn version_grows_with_the_payload_07() { |
| 107 | // The side length is version * 4 + 17, and a longer payload forces a larger version. |
| 108 | let small = match encode("a", QrEcc::Low) { |
| 109 | Ok(q) => q, |
| 110 | Err(e) => panic!("encode failed: {:?}", e), |
| 111 | }; |
| 112 | assert_eq!(small.version(), 1); |
| 113 | assert_eq!(small.size(), 21); |
| 114 | |
| 115 | let mut last = 0u8; |
| 116 | for len in [10usize, 100, 400, 1000, 2000] { |
| 117 | let text = "z".repeat(len); |
| 118 | let qr = match encode(&text, QrEcc::Low) { |
| 119 | Ok(q) => q, |
| 120 | Err(e) => panic!("encode failed at len {}: {:?}", len, e), |
| 121 | }; |
| 122 | assert!(qr.version() >= last, "version should not shrink as data grows"); |
| 123 | assert_eq!(qr.size(), qr.version() as usize * 4 + 17); |
| 124 | last = qr.version(); |
| 125 | } |
| 126 | } |
| 127 | |
| 128 | #[test] |
| 129 | fn overlong_payload_is_refused_08() { |
| 130 | // Version 40 at High holds well under 3000 data bytes, so this cannot fit. |
| 131 | let text = "q".repeat(5000); |
| 132 | assert!(encode(&text, QrEcc::High).is_err()); |
| 133 | } |
| 134 | |
| 135 | #[test] |
| 136 | fn forced_mask_and_version_are_honoured_09() { |
| 137 | // The advanced entry point can pin a version and mask; the size must follow the version. |
| 138 | let qr = match encode_bytes_advanced(b"pinned", QrEcc::Low, 5, 5, Some(3), false) { |
| 139 | Ok(q) => q, |
| 140 | Err(e) => panic!("encode failed: {:?}", e), |
| 141 | }; |
| 142 | assert_eq!(qr.version(), 5); |
| 143 | assert_eq!(qr.size(), 37); |
| 144 | assert_eq!(qr.ecc(), QrEcc::Low); // Boosting is off, so the level is exactly as asked. |
| 145 | } |
| 146 | |
| 147 | #[test] |
| 148 | fn bad_arguments_are_rejected_10() { |
| 149 | assert!(encode_bytes_advanced(b"x", QrEcc::Low, 0, 40, None, true).is_err()); |
| 150 | assert!(encode_bytes_advanced(b"x", QrEcc::Low, 1, 41, None, true).is_err()); |
| 151 | assert!(encode_bytes_advanced(b"x", QrEcc::Low, 10, 5, None, true).is_err()); |
| 152 | assert!(encode_bytes_advanced(b"x", QrEcc::Low, 1, 40, Some(8), true).is_err()); |
| 153 | } |
| 154 | |
| 155 | // -- Golden matrices from qrcodegen 1.8 (byte mode, boosted error correction). -- |
| 156 | |
| 157 | const HELLO_BYTE_LOW: &str = " |
| 158 | 111111101001001111111 |
| 159 | 100000100100001000001 |
| 160 | 101110101001001011101 |
| 161 | 101110101011001011101 |
| 162 | 101110100110101011101 |
| 163 | 100000101101001000001 |
| 164 | 111111101010101111111 |
| 165 | 000000001011100000000 |
| 166 | 010101111001111101101 |
| 167 | 001111000100001100010 |
| 168 | 010010110101100101101 |
| 169 | 101110010111101011011 |
| 170 | 010110101011011110100 |
| 171 | 000000001100100010100 |
| 172 | 111111101101001111110 |
| 173 | 100000101111100100001 |
| 174 | 101110100100111000110 |
| 175 | 101110101010000111111 |
| 176 | 101110100010101010101 |
| 177 | 100000101011010000000 |
| 178 | 111111100010100101110 |
| 179 | "; |
| 180 | |
| 181 | const URL_MEDIUM: &str = " |
| 182 | 1111111010011001001111111 |
| 183 | 1000001010001001101000001 |
| 184 | 1011101010001011001011101 |
| 185 | 1011101010101010001011101 |
| 186 | 1011101010110011001011101 |
| 187 | 1000001001000011001000001 |
| 188 | 1111111010101010101111111 |
| 189 | 0000000011101110100000000 |
| 190 | 0110101100111011101011111 |
| 191 | 0110010101100000001000001 |
| 192 | 0001001001001100000110111 |
| 193 | 1001000100110001110000010 |
| 194 | 0100001110000000111001011 |
| 195 | 0110110010100100111001001 |
| 196 | 1010101100101010101100111 |
| 197 | 0110110110001011100010010 |
| 198 | 1001111001110101111111000 |
| 199 | 0000000010001101100011011 |
| 200 | 1111111010111011101011011 |
| 201 | 1000001001110010100011001 |
| 202 | 1011101011010100111111001 |
| 203 | 1011101001111001000111100 |
| 204 | 1011101010001100100010001 |
| 205 | 1000001010010000101011010 |
| 206 | 1111111000110001111100011 |
| 207 | "; |
| 208 | |
| 209 | const PAIR_QUARTILE: &str = " |
| 210 | 111111101101000100110011001111111 |
| 211 | 100000101001101011010001101000001 |
| 212 | 101110101010011110001001001011101 |
| 213 | 101110101100111011010100101011101 |
| 214 | 101110101011010010000111101011101 |
| 215 | 100000100000000011000011001000001 |
| 216 | 111111101010101010101010101111111 |
| 217 | 000000001010101001101100000000000 |
| 218 | 011010110100010111010100101011111 |
| 219 | 000110011010000000001000111100011 |
| 220 | 011110111101110001000100011100111 |
| 221 | 110100011011001110001001110010001 |
| 222 | 000111111111100000010001011001010 |
| 223 | 110010010000000100010100010001101 |
| 224 | 100110101100010101100000010101011 |
| 225 | 010100000100011101110101001101010 |
| 226 | 001000110111010111001110111001000 |
| 227 | 100011001100100010100100111100001 |
| 228 | 011000111101001001001010011000101 |
| 229 | 100101001011101111010111000110011 |
| 230 | 000001101110010101001011011011001 |
| 231 | 010100011001111100111010011000111 |
| 232 | 101100100101101010011100111001111 |
| 233 | 010100000001111000101101010100000 |
| 234 | 100100111101000111110100111110111 |
| 235 | 000000001101110010101001100011001 |
| 236 | 111111101100011000001101101010111 |
| 237 | 100000100011110010110000100010000 |
| 238 | 101110101110001111000000111111000 |
| 239 | 101110100011010100010100000011011 |
| 240 | 101110101001011011100010100011101 |
| 241 | 100000101010111001110110100010010 |
| 242 | 111111100101101101100100100010011 |
| 243 | "; |
| 244 | |
| 245 | const LONG_HIGH: &str = " |
| 246 | 1111111011111101110100000000010010011111111000001001101111111 |
| 247 | 1000001010010110100000011010111001001111010010100001101000001 |
| 248 | 1011101011000110101011011111111011001100101111111011101011101 |
| 249 | 1011101001110010011111110101010110011110111101001110101011101 |
| 250 | 1011101001000100010100110001111110011011101000011111001011101 |
| 251 | 1000001010000111100000010100100011001101011010101110001000001 |
| 252 | 1111111010101010101010101010101010101010101010101010101111111 |
| 253 | 0000000011000110101011001111100011001110110111110011100000000 |
| 254 | 0011101011111010011111010101111110011010100101011000111100111 |
| 255 | 1001010101001100010100010111111000011001110000001100011001110 |
| 256 | 0111001001011111101001010101111001001011001010100111010011011 |
| 257 | 0101000011100110110010001111101011010110100111110011100110001 |
| 258 | 1101101000000010000111110100110010001010101101011000101100100 |
| 259 | 0001010111110100100101110110100000010001111000001100011001110 |
| 260 | 0100001001011110000001010101010001000101010010100111010011011 |
| 261 | 0100000011111110101010001111011010110110100111110011100110001 |
| 262 | 1101101000000011100101110100100010101110101101011000101100101 |
| 263 | 0001010111110100101011110111000000110101111000001100011001101 |
| 264 | 0010001001011110010001110100110001100011010010100111010011010 |
| 265 | 0000000111111111001011001110111010010110100111110011100110000 |
| 266 | 0001101010000010111101110101100011011110101101011000101100110 |
| 267 | 1000010111110100100011110111100000110101111000001100011001110 |
| 268 | 0001001011011000101001110100111000011011010010100111010011011 |
| 269 | 0000000101111000010011001110110011110100100111110011100000001 |
| 270 | 0001101010000110101011110101111010011101101101011001001110100 |
| 271 | 1000010111110001011101110111100001101001111000001100111011110 |
| 272 | 0001001101011110101111110100111000001010010010100111110111011 |
| 273 | 0000000111111111010101001110110010110100100111110000100110001 |
| 274 | 0001111110000100101011100101111111001101101101011100111110100 |
| 275 | 1000100011110101011101110110100011000001111000001000100011110 |
| 276 | 0001101011011000101101100001101010101010010010100100101011011 |
| 277 | 0000100011111001010101000100100010110101100111110011100010001 |
| 278 | 0001111110000100110111100010111111011101001101011001111110100 |
| 279 | 1000100001110101001111110110111011010000111000001101001101110 |
| 280 | 0001011011011000101111100010000000100011010010100110111001011 |
| 281 | 0000000100111001010011000110011000110101000101110010110010001 |
| 282 | 0001101001001010110111101110110010111100101001011001000110100 |
| 283 | 1000100000101011001011111000111010110001111101001101001101110 |
| 284 | 0001011100011000101101100110000011100010110001000110111001011 |
| 285 | 0000000010100001010101011100011100110100000000110010110010001 |
| 286 | 0001101000001010110111110000110000111101001111111001001110100 |
| 287 | 1000100000101011001011101110111010110000011010101101011101010 |
| 288 | 1001111101011100101101111100000011100011010111000110101000011 |
| 289 | 0000100010100111010100010110011100110100100111110010111011001 |
| 290 | 0110111000101110110110000000010000111100001101011001000110000 |
| 291 | 0101000001011001001010001100011010110001011000001101001101110 |
| 292 | 1010011101111100101100010100100011100011110010100110111001011 |
| 293 | 1101100011111111010101011111111000110100110111101010110010001 |
| 294 | 1010001001001111110110011001010010111110000101010001000110100 |
| 295 | 1001110001011000101010010100011110110001010000000101001101110 |
| 296 | 0011111101100100001101101010100111100011101010110110111001011 |
| 297 | 1110100011101110110100100001100010110000101111110010110010001 |
| 298 | 1111001001001111110110011111111110111110011101011001111110100 |
| 299 | 0000000011000000101010010100100010110101001000001101100011110 |
| 300 | 1111111001110100010100101011101011100001111010100111101011011 |
| 301 | 1000001000010110101100000000100010110100100111110011100010001 |
| 302 | 1011101011001110001111011111111110110010001101011000111110100 |
| 303 | 1011101011010001110011010100010100100011011000001100100111101 |
| 304 | 1011101011110101101100101010111001101001110010100110001101001 |
| 305 | 1000001000011110010100000001111110010000100111110011011000001 |
| 306 | 1111111001001111000001011110010100110010001101011001110010111 |
| 307 | "; |
| 308 | |
| 309 | const VER7PLUS: &str = " |
| 310 | 1111111011101011100011100000110000101010101010101101101111111 |
| 311 | 1000001011000011001100101011010101101110111011101101101000001 |
| 312 | 1011101001101011101100100011001011000100010001000111101011101 |
| 313 | 1011101001010101110111011101111011010101010101010110101011101 |
| 314 | 1011101011101000100010001000111110101010101010101011001011101 |
| 315 | 1000001010111011011100110010100011101110111011101110001000001 |
| 316 | 1111111010101010101010101010101010101010101010101010101111111 |
| 317 | 0000000010110100101011001101100010111011101110111010100000000 |
| 318 | 1110011011100010000010100011111110101010101010101010011110011 |
| 319 | 0010110100011111000001110110101111010101010101010101010100111 |
| 320 | 1000011111000100110011001100001010010001000100010000100100101 |
| 321 | 1101010100111100110001001101010100111011101110111010101111010 |
| 322 | 0111001001101010001000100010100100101010101010101010001010010 |
| 323 | 0000010101111111011101110110101111010101010101010101010100111 |
| 324 | 1010101110101000110011101100001010010001000100010000100100101 |
| 325 | 1011000000110010110011001101010100111011101110111010101111010 |
| 326 | 1010111010101001101001101010100100101010101010101010001010010 |
| 327 | 1110100110111001111101000110101111010101010101010101010100111 |
| 328 | 0010111010101001010011001100001010010001000100010000100100101 |
| 329 | 1110110010110011110011000101010100111011101110111010101111010 |
| 330 | 0010011010101110001000100010100100101010101010101010001010010 |
| 331 | 0011110100101111011101110110101111010101010101010101010100111 |
| 332 | 1101001111111110111011001100001010010001000100010000100100101 |
| 333 | 0010110100000110110011001101010100111011101110111010101111010 |
| 334 | 1010011010101000011110100010100100101010101010101010001010010 |
| 335 | 0011110010101001010111110110101111010101010101010101010100111 |
| 336 | 1101001000011110110101001100001010010001000100010000100100101 |
| 337 | 0010010101100110110111001101010100111011101110111010101111000 |
| 338 | 1001111110110000001000100010111110101010101010101010111110000 |
| 339 | 0000100011011001011101110110100011010101010101010101100010111 |
| 340 | 1000101011110100110010001101101010010001000100010000101010101 |
| 341 | 1000100011001100110010101101100010111011101110111010100011010 |
| 342 | 0001111110110100101000011010111110101010101010101010111110010 |
| 343 | 0111010100011100011100011111111011010101010101010100010100111 |
| 344 | 0001011101110110110011010101010000010001000100010000001010101 |
| 345 | 0000100111001010010011011100010100111011101110111011111011010 |
| 346 | 0100101000111100001000100010001010101010101010101011010000010 |
| 347 | 1111000010000011011101110111111011010101010101010100010100111 |
| 348 | 1100101100100110100011001101010000010001000100010000001010101 |
| 349 | 1100110011101110101011001100010100111011101110111011111011010 |
| 350 | 0100101001010000000010100110001010101010101010101011010000010 |
| 351 | 1011100101110001000001110001111011010101010101010100010100101 |
| 352 | 1100101011000110110011001101010000010001000100010000001010111 |
| 353 | 1100010010111110110001001100010100111011101110111011111011010 |
| 354 | 0101101010001000001000100010001010101010101010101011010000011 |
| 355 | 1011100011100001011101110111111011010101010101010100010100111 |
| 356 | 0110101101001000110011101101010000010001000100010000001010101 |
| 357 | 1111010111100000110011001100010100111011101110111011111011010 |
| 358 | 0101111010001101101001101010001010101010101010101011010000010 |
| 359 | 1100010010000001111101000111111011010101010101010100010100111 |
| 360 | 0011111101001011010011001101010000010001000100010000001010101 |
| 361 | 1110100111100001110011000100010100111011101110111011111011010 |
| 362 | 1111001100010010001000100010111110101010101010101011111110010 |
| 363 | 0000000010010011011101110111100011010101010101010101100010111 |
| 364 | 1111111000001010111011001000101010010001000100010001101010101 |
| 365 | 1000001010101000110011001011100010111011101110111010100011010 |
| 366 | 1011101000011110011110100001111110101010101010101010111110010 |
| 367 | 1011101001011111010111110001010101010101010101010101101110100 |
| 368 | 1011101010000010110101001101000100010001000100010000101010111 |
| 369 | 1000001010100000110111001101101110111011101110111011010101000 |
| 370 | 1111111010000110001000100010101010101010101010101011000100001 |
| 371 | "; |