summaryrefslogtreecommitdiff
path: root/tools/check_codes.py
blob: 22d303309e20007e8752d93b732144182f371c45 (plain) (blame)
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
#!/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]+)")
SCALES = (1, 2, 3)


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
    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())