92 lines
3.7 KiB
Python
92 lines
3.7 KiB
Python
"""Cells for oracle_dl.py (Q85): the independent oracle for damerau_levenshtein.
|
|
|
|
`oracle_dl.py` is a CLI with the repo's 0/1/2 contract and no collected cell, so
|
|
its two graded properties -- it agrees with the BFS oracle, and its corpus
|
|
actually separates true Damerau-Levenshtein from OSA and from plain Levenshtein
|
|
-- were only ever measured by hand. The cells use `run(module, pairs, teeth)`
|
|
with a short corpus so the lane stays fast; the corpus is asserted to be
|
|
deterministic and large separately.
|
|
|
|
Note measured while writing this, not repaired here (it is beam's file): the
|
|
docstring advertises `--teeth`, but argparse has only `--no-teeth` -- teeth are
|
|
the default -- so `python3 oracle_dl.py --teeth` exits 2 as an unrecognised
|
|
argument. These cells call `run()` directly and do not depend on the flag.
|
|
"""
|
|
import contextlib
|
|
import io
|
|
import os
|
|
import types
|
|
import unittest
|
|
|
|
import damerau_levenshtein as DL
|
|
import oracle_dl as O
|
|
|
|
PAIRS = [("ca", "abc"), ("abc", "acb"), ("ab", "ba"), ("", ""),
|
|
("aab", "abca"), ("abcd", "badc"), ("a", "b"), ("abcd", "dcba")]
|
|
|
|
|
|
def _module(fn):
|
|
return types.SimpleNamespace(damerau_levenshtein=fn)
|
|
|
|
|
|
class TestOracleDl(unittest.TestCase):
|
|
def _run(self, module, pairs=PAIRS, teeth=True):
|
|
out = io.StringIO()
|
|
with contextlib.redirect_stdout(out):
|
|
rc = O.run(module, pairs, teeth)
|
|
return rc, out.getvalue()
|
|
|
|
def test_the_shipped_module_agrees_with_the_oracle(self):
|
|
rc, out = self._run(_module(DL.damerau_levenshtein))
|
|
self.assertEqual(rc, 0, out)
|
|
self.assertIn("0 mismatches against the BFS oracle", out)
|
|
|
|
def test_the_corpus_catches_osa(self):
|
|
# The witness Q133-DL was written for: true DL("ca","abc") is 2, OSA
|
|
# says 3. A corpus that cannot red an OSA implementation reports green
|
|
# on a broken module too.
|
|
rc, out = self._run(_module(O.osa))
|
|
self.assertEqual(rc, 1, out)
|
|
self.assertIn("FAIL", out)
|
|
|
|
def test_the_corpus_catches_plain_levenshtein(self):
|
|
rc, out = self._run(_module(O.levenshtein))
|
|
self.assertEqual(rc, 1, out)
|
|
self.assertIn("FAIL", out)
|
|
|
|
def test_teeth_off_still_grades_the_corpus(self):
|
|
rc, out = self._run(_module(DL.damerau_levenshtein), teeth=False)
|
|
self.assertEqual(rc, 0, out)
|
|
self.assertNotIn("teeth:", out)
|
|
|
|
def test_the_full_corpus_is_deterministic_and_large(self):
|
|
first = O.corpus()
|
|
self.assertEqual(first, O.corpus(), "the corpus must be the same on every run")
|
|
self.assertGreater(len(first), 1000)
|
|
for pair in first[:100]:
|
|
self.assertEqual(len(pair), 2)
|
|
self.assertTrue(all(isinstance(s, str) for s in pair), pair)
|
|
|
|
def test_a_missing_module_cannot_be_graded(self):
|
|
err = io.StringIO()
|
|
with contextlib.redirect_stderr(err), contextlib.redirect_stdout(io.StringIO()):
|
|
rc = O.main(["--module", os.path.join(os.sep, "nonexistent", "dl.py")])
|
|
self.assertEqual(rc, 2, err.getvalue())
|
|
self.assertIn("could not grade", err.getvalue())
|
|
|
|
def test_a_module_without_the_entry_point_cannot_be_graded(self):
|
|
import tempfile
|
|
with tempfile.TemporaryDirectory(prefix="oracle-dl.") as tmp:
|
|
path = os.path.join(tmp, "empty_module.py")
|
|
with open(path, "w", encoding="utf-8") as fh:
|
|
fh.write("value = 1\n")
|
|
err = io.StringIO()
|
|
with contextlib.redirect_stderr(err), contextlib.redirect_stdout(io.StringIO()):
|
|
rc = O.main(["--module", path])
|
|
self.assertEqual(rc, 2, err.getvalue())
|
|
self.assertIn("no damerau_levenshtein()", err.getvalue())
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|