1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
#!/usr/bin/env python3
# Author: cirakg & claude ai
# Summary: Decode the barcodes the watch's encoders produced in a unit-test run with zxing-cpp (README 12.4 check 2).
"""Decode-check the CODEDUMP lines of a Monkey C test log.
Each line is "CODEDUMP <symbology> <readable text as hex> <modules>". Every
code is rendered with its quiet zone at 1, 2 and 3 pixels per module and
must decode to the expected text at each size.
Usage: check_codes.py LOG [LOG ...] Exit: 0 all decoded, 1 a failure, 2 no dump found.
"""
from __future__ import annotations
import re
import sys
from pathlib import Path
import barcode_ref as ref
DUMP = re.compile(r"CODEDUMP (\d+) ([0-9a-f]*) ([01]+)")
QR_DUMP = re.compile(r"QRDUMP (\d+) ([0-9a-f]*) ([0-9a-f]+)")
SCALES = (1, 2, 3)
QR_SCALES = (2, 3) # README 12.2: 2D codes use at least 2 px per module
def check_log(path: Path) -> tuple[int, list[str]]:
"""(codes checked, failure messages) for one log."""
checked = 0
failures: list[str] = []
for match in DUMP.finditer(path.read_text(encoding="utf-8", errors="replace")):
symbology = int(match.group(1))
text = bytes.fromhex(match.group(2)).decode("utf-8")
modules = match.group(3)
expected = ref.expected_reading(symbology, text)
for scale in SCALES:
got = ref.decode(ref.render_linear(modules, scale), symbology)
if expected not in got:
failures.append(f"symbology {symbology} '{text}' at {scale} px/module: read {got}")
checked += 1
for match in QR_DUMP.finditer(path.read_text(encoding="utf-8", errors="replace")):
size = int(match.group(1))
text = bytes.fromhex(match.group(2)).decode("utf-8")
packed = bytes.fromhex(match.group(3))
for scale in QR_SCALES:
got = ref.decode(ref.render_matrix(packed, size, scale, quiet=4), ref.QR)
if text not in got:
failures.append(f"QR size {size} '{text[:30]}' at {scale} px/module: read {got}")
checked += 1
return checked, failures
def main(argv: list[str] | None = None) -> int:
paths = [Path(p) for p in (argv if argv is not None else sys.argv[1:])]
total = 0
failed = False
for path in paths:
checked, failures = check_log(path)
total += checked
for failure in failures[:10]:
print(f"[{path.stem}] {failure}")
failed = failed or bool(failures)
print(f"[{path.stem}] decoded {checked} barcodes at {len(SCALES)} sizes: {'FAILED' if failures else 'ok'}")
if total == 0:
print("no CODEDUMP lines found")
return 2
return 1 if failed else 0
if __name__ == "__main__":
raise SystemExit(main())
|