90 lines
2.7 KiB
Python
90 lines
2.7 KiB
Python
#!/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(source=None):
|
||
args = [sys.executable, "-B", str(MKEMOJI)]
|
||
if source is not None:
|
||
args.append(str(source))
|
||
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)
|
||
self.assertEqual(data["^"].split()[:9], list("¹²³⁴⁵⁶⁷⁸⁹"))
|
||
self.assertEqual(data["_"].split()[:9], list("₁₂₃₄₅₆₇₈₉"))
|
||
self.assertEqual(data["<"].split()[2], "♥")
|
||
self.assertEqual(data["^1"], "¹")
|
||
self.assertEqual(data["_2"], "₂")
|
||
self.assertEqual(data["<3"], "♥")
|
||
|
||
def test_fold_normalize_and_exact_first(self):
|
||
source = self.source(
|
||
"β\tALPHABET\n"
|
||
"α\talpha\n"
|
||
"e\u0301\tE\u0301\n"
|
||
"#\thash\n"
|
||
)
|
||
first = generate(source)
|
||
second = generate(source)
|
||
self.assertEqual(first.returncode, 0, first.stderr)
|
||
self.assertEqual(first.stdout, second.stdout)
|
||
data = table(first.stdout)
|
||
self.assertEqual(data["alpha"].split(), ["α", "β"])
|
||
self.assertEqual(data["al"].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()
|