Oregami
Repositories/oxedyne/fe2o3

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
13use super::*;
14
15/// Renders a matrix as rows of `0` and `1` so it can be compared against a golden literal.
16fn 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
29fn 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]
40fn matches_oracle_hello_byte_low_00() {
41 check("HELLO WORLD", QrEcc::Low, 1, 21, HELLO_BYTE_LOW);
42}
43
44#[test]
45fn matches_oracle_url_medium_01() {
46 check("https://example.org", QrEcc::Medium, 2, 25, URL_MEDIUM);
47}
48
49#[test]
50fn matches_oracle_pair_quartile_02() {
51 check("https://daimond.app/pair?k=AbCdEf0123", QrEcc::Quartile, 4, 33, PAIR_QUARTILE);
52}
53
54#[test]
55fn matches_oracle_long_high_03() {
56 let text = "x".repeat(120);
57 check(&text, QrEcc::High, 11, 61, LONG_HIGH);
58}
59
60#[test]
61fn 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]
68fn 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]
91fn 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]
106fn 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]
129fn 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]
136fn 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]
148fn 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
157const HELLO_BYTE_LOW: &str = "
158111111101001001111111
159100000100100001000001
160101110101001001011101
161101110101011001011101
162101110100110101011101
163100000101101001000001
164111111101010101111111
165000000001011100000000
166010101111001111101101
167001111000100001100010
168010010110101100101101
169101110010111101011011
170010110101011011110100
171000000001100100010100
172111111101101001111110
173100000101111100100001
174101110100100111000110
175101110101010000111111
176101110100010101010101
177100000101011010000000
178111111100010100101110
179";
180
181const URL_MEDIUM: &str = "
1821111111010011001001111111
1831000001010001001101000001
1841011101010001011001011101
1851011101010101010001011101
1861011101010110011001011101
1871000001001000011001000001
1881111111010101010101111111
1890000000011101110100000000
1900110101100111011101011111
1910110010101100000001000001
1920001001001001100000110111
1931001000100110001110000010
1940100001110000000111001011
1950110110010100100111001001
1961010101100101010101100111
1970110110110001011100010010
1981001111001110101111111000
1990000000010001101100011011
2001111111010111011101011011
2011000001001110010100011001
2021011101011010100111111001
2031011101001111001000111100
2041011101010001100100010001
2051000001010010000101011010
2061111111000110001111100011
207";
208
209const PAIR_QUARTILE: &str = "
210111111101101000100110011001111111
211100000101001101011010001101000001
212101110101010011110001001001011101
213101110101100111011010100101011101
214101110101011010010000111101011101
215100000100000000011000011001000001
216111111101010101010101010101111111
217000000001010101001101100000000000
218011010110100010111010100101011111
219000110011010000000001000111100011
220011110111101110001000100011100111
221110100011011001110001001110010001
222000111111111100000010001011001010
223110010010000000100010100010001101
224100110101100010101100000010101011
225010100000100011101110101001101010
226001000110111010111001110111001000
227100011001100100010100100111100001
228011000111101001001001010011000101
229100101001011101111010111000110011
230000001101110010101001011011011001
231010100011001111100111010011000111
232101100100101101010011100111001111
233010100000001111000101101010100000
234100100111101000111110100111110111
235000000001101110010101001100011001
236111111101100011000001101101010111
237100000100011110010110000100010000
238101110101110001111000000111111000
239101110100011010100010100000011011
240101110101001011011100010100011101
241100000101010111001110110100010010
242111111100101101101100100100010011
243";
244
245const LONG_HIGH: &str = "
2461111111011111101110100000000010010011111111000001001101111111
2471000001010010110100000011010111001001111010010100001101000001
2481011101011000110101011011111111011001100101111111011101011101
2491011101001110010011111110101010110011110111101001110101011101
2501011101001000100010100110001111110011011101000011111001011101
2511000001010000111100000010100100011001101011010101110001000001
2521111111010101010101010101010101010101010101010101010101111111
2530000000011000110101011001111100011001110110111110011100000000
2540011101011111010011111010101111110011010100101011000111100111
2551001010101001100010100010111111000011001110000001100011001110
2560111001001011111101001010101111001001011001010100111010011011
2570101000011100110110010001111101011010110100111110011100110001
2581101101000000010000111110100110010001010101101011000101100100
2590001010111110100100101110110100000010001111000001100011001110
2600100001001011110000001010101010001000101010010100111010011011
2610100000011111110101010001111011010110110100111110011100110001
2621101101000000011100101110100100010101110101101011000101100101
2630001010111110100101011110111000000110101111000001100011001101
2640010001001011110010001110100110001100011010010100111010011010
2650000000111111111001011001110111010010110100111110011100110000
2660001101010000010111101110101100011011110101101011000101100110
2671000010111110100100011110111100000110101111000001100011001110
2680001001011011000101001110100111000011011010010100111010011011
2690000000101111000010011001110110011110100100111110011100000001
2700001101010000110101011110101111010011101101101011001001110100
2711000010111110001011101110111100001101001111000001100111011110
2720001001101011110101111110100111000001010010010100111110111011
2730000000111111111010101001110110010110100100111110000100110001
2740001111110000100101011100101111111001101101101011100111110100
2751000100011110101011101110110100011000001111000001000100011110
2760001101011011000101101100001101010101010010010100100101011011
2770000100011111001010101000100100010110101100111110011100010001
2780001111110000100110111100010111111011101001101011001111110100
2791000100001110101001111110110111011010000111000001101001101110
2800001011011011000101111100010000000100011010010100110111001011
2810000000100111001010011000110011000110101000101110010110010001
2820001101001001010110111101110110010111100101001011001000110100
2831000100000101011001011111000111010110001111101001101001101110
2840001011100011000101101100110000011100010110001000110111001011
2850000000010100001010101011100011100110100000000110010110010001
2860001101000001010110111110000110000111101001111111001001110100
2871000100000101011001011101110111010110000011010101101011101010
2881001111101011100101101111100000011100011010111000110101000011
2890000100010100111010100010110011100110100100111110010111011001
2900110111000101110110110000000010000111100001101011001000110000
2910101000001011001001010001100011010110001011000001101001101110
2921010011101111100101100010100100011100011110010100110111001011
2931101100011111111010101011111111000110100110111101010110010001
2941010001001001111110110011001010010111110000101010001000110100
2951001110001011000101010010100011110110001010000000101001101110
2960011111101100100001101101010100111100011101010110110111001011
2971110100011101110110100100001100010110000101111110010110010001
2981111001001001111110110011111111110111110011101011001111110100
2990000000011000000101010010100100010110101001000001101100011110
3001111111001110100010100101011101011100001111010100111101011011
3011000001000010110101100000000100010110100100111110011100010001
3021011101011001110001111011111111110110010001101011000111110100
3031011101011010001110011010100010100100011011000001100100111101
3041011101011110101101100101010111001101001110010100110001101001
3051000001000011110010100000001111110010000100111110011011000001
3061111111001001111000001011110010100110010001101011001110010111
307";
308
309const VER7PLUS: &str = "
3101111111011101011100011100000110000101010101010101101101111111
3111000001011000011001100101011010101101110111011101101101000001
3121011101001101011101100100011001011000100010001000111101011101
3131011101001010101110111011101111011010101010101010110101011101
3141011101011101000100010001000111110101010101010101011001011101
3151000001010111011011100110010100011101110111011101110001000001
3161111111010101010101010101010101010101010101010101010101111111
3170000000010110100101011001101100010111011101110111010100000000
3181110011011100010000010100011111110101010101010101010011110011
3190010110100011111000001110110101111010101010101010101010100111
3201000011111000100110011001100001010010001000100010000100100101
3211101010100111100110001001101010100111011101110111010101111010
3220111001001101010001000100010100100101010101010101010001010010
3230000010101111111011101110110101111010101010101010101010100111
3241010101110101000110011101100001010010001000100010000100100101
3251011000000110010110011001101010100111011101110111010101111010
3261010111010101001101001101010100100101010101010101010001010010
3271110100110111001111101000110101111010101010101010101010100111
3280010111010101001010011001100001010010001000100010000100100101
3291110110010110011110011000101010100111011101110111010101111010
3300010011010101110001000100010100100101010101010101010001010010
3310011110100101111011101110110101111010101010101010101010100111
3321101001111111110111011001100001010010001000100010000100100101
3330010110100000110110011001101010100111011101110111010101111010
3341010011010101000011110100010100100101010101010101010001010010
3350011110010101001010111110110101111010101010101010101010100111
3361101001000011110110101001100001010010001000100010000100100101
3370010010101100110110111001101010100111011101110111010101111000
3381001111110110000001000100010111110101010101010101010111110000
3390000100011011001011101110110100011010101010101010101100010111
3401000101011110100110010001101101010010001000100010000101010101
3411000100011001100110010101101100010111011101110111010100011010
3420001111110110100101000011010111110101010101010101010111110010
3430111010100011100011100011111111011010101010101010100010100111
3440001011101110110110011010101010000010001000100010000001010101
3450000100111001010010011011100010100111011101110111011111011010
3460100101000111100001000100010001010101010101010101011010000010
3471111000010000011011101110111111011010101010101010100010100111
3481100101100100110100011001101010000010001000100010000001010101
3491100110011101110101011001100010100111011101110111011111011010
3500100101001010000000010100110001010101010101010101011010000010
3511011100101110001000001110001111011010101010101010100010100101
3521100101011000110110011001101010000010001000100010000001010111
3531100010010111110110001001100010100111011101110111011111011010
3540101101010001000001000100010001010101010101010101011010000011
3551011100011100001011101110111111011010101010101010100010100111
3560110101101001000110011101101010000010001000100010000001010101
3571111010111100000110011001100010100111011101110111011111011010
3580101111010001101101001101010001010101010101010101011010000010
3591100010010000001111101000111111011010101010101010100010100111
3600011111101001011010011001101010000010001000100010000001010101
3611110100111100001110011000100010100111011101110111011111011010
3621111001100010010001000100010111110101010101010101011111110010
3630000000010010011011101110111100011010101010101010101100010111
3641111111000001010111011001000101010010001000100010001101010101
3651000001010101000110011001011100010111011101110111010100011010
3661011101000011110011110100001111110101010101010101010111110010
3671011101001011111010111110001010101010101010101010101101110100
3681011101010000010110101001101000100010001000100010000101010111
3691000001010100000110111001101101110111011101110111011010101000
3701111111010000110001000100010101010101010101010101011000100001
371";