#!/usr/bin/env python3 import subprocess import sys import tempfile import unittest from pathlib import Path ROOT = Path(__file__).resolve().parents[1] MKEMOJI = ROOT / "map" / "mkemoji" TIMEOUT = 10 def generate(*sources): args = [sys.executable, "-B", str(MKEMOJI)] + [str(s) for s in sources] return subprocess.run( args, capture_output=True, text=True, check=False, timeout=TIMEOUT ) def table(output): return dict(line.split("\t", 1) for line in output.splitlines()) class MkemojiTest(unittest.TestCase): def source(self, text): tmp = tempfile.TemporaryDirectory() path = Path(tmp.name) / "emoji.src" path.write_text(text, encoding="utf-8") self.addCleanup(tmp.cleanup) return path def test_production_digit_slots(self): result = generate() self.assertEqual(result.returncode, 0, result.stderr) data = table(result.stdout) keys = list(data) self.assertEqual([k for k in keys if k[:1] == "^"][:9], [f"^{d}" for d in range(1, 10)]) self.assertEqual([k for k in keys if k[:1] == "_"][:9], [f"_{d}" for d in range(1, 10)]) self.assertEqual([k for k in keys if k[:1] == "<"][2], "<3") self.assertEqual(data["^1"], "¹") self.assertEqual(data["_2"], "₂") self.assertEqual(data["<3"].split()[0], "♥") self.assertIn("😀", data["smile"].split()) self.assertIn("😀", data["웃음"].split()) def test_fold_normalize_and_source_order(self): source = self.source( "β\tALPHABET\talpha\n" "α\talpha\n" "é\tÉ\n" "#\thash\n" ) first = generate(source) second = generate(source, source) self.assertEqual(first.returncode, 0, first.stderr) self.assertEqual(first.stdout, second.stdout) data = table(first.stdout) self.assertEqual(list(data), ["alphabet", "alpha", "é", "hash"]) self.assertEqual(data["alpha"].split(), ["β", "α"]) self.assertEqual(data["é"], "é") self.assertEqual(data["hash"], "#") def test_rejects_malformed_and_oversized_rows(self): bad = [ "x\n", "bad result\ta\n", "x\t\n", "x\t a\n", "\0\ta\n", "x\ta\0b\n", "x\t;hidden\n", "x" * 65 + "\ta\n", "x\t" + "a" * 65 + "\n", ] for text in bad: with self.subTest(text=repr(text)): result = generate(self.source(text)) self.assertEqual(result.returncode, 1) def test_accepts_runtime_boundary(self): source = self.source("x" * 64 + "\t" + "a" * 64 + "\n") result = generate(source) self.assertEqual(result.returncode, 0, result.stderr) self.assertIn("a" * 64 + "\t" + "x" * 64, result.stdout) if __name__ == "__main__": unittest.main()