"""Regression fixtures for publication audit failures; no external dependencies."""
import importlib.util
import json
import sys
import tempfile
import unittest
from pathlib import Path
SCRIPTS = Path(__file__).resolve().parents[1] / 'scripts'
spec = importlib.util.spec_from_file_location('verify_output', SCRIPTS / 'verify_output.py')
verify = importlib.util.module_from_spec(spec)
sys.modules[spec.name] = verify
spec.loader.exec_module(verify)
spec = importlib.util.spec_from_file_location('review_output', SCRIPTS / 'review_output.py')
review = importlib.util.module_from_spec(spec)
spec.loader.exec_module(review)
class OutputAuditTests(unittest.TestCase):
def setUp(self):
self.temp = tempfile.TemporaryDirectory()
self.addCleanup(self.temp.cleanup)
self.root = Path(self.temp.name)
self.baseline = {('genesis', 1, 1): '神が天と地を創造した。'}
def write(self, verses=None, **metadata):
directory = self.root / 'genesis'
directory.mkdir(exist_ok=True)
path = directory / 'chapter_01.json'
path.write_text(json.dumps({'book': 'genesis', 'chapter': 1,
'verses': verses if verses is not None else {'1': {'text': '神が創造した。'}},
**metadata}), encoding='utf-8')
return path
def codes(self):
return set(verify.audit(self.root, self.baseline)[0]['summary']['issues'])
def test_complete_and_optional_furigana(self):
for ruby in (None, '', '神が創造した。', '神が創造した。'):
with self.subTest(ruby=ruby):
self.write({'1': {'text': '神が創造した。', 'text_with_furigana': ruby}})
self.assertEqual(self.codes(), set())
def test_missing_source_fails_closed(self):
report, _ = verify.audit(self.root / 'absent', self.baseline)
self.assertFalse(report['passed'])
self.assertIn('missing-source', report['summary']['issues'])
def test_duplicate_json_key(self):
self.write().write_text('{"verses":{"1":{},"1":{}}}')
self.assertIn('invalid-json', self.codes())
def test_malformed_and_wrong_schema(self):
for content in ('{', '[]', '{"verses": []}'):
with self.subTest(content=content):
self.write().write_text(content)
self.assertTrue(self.codes() & {'invalid-json', 'invalid-schema'})
def test_mismatched_metadata(self):
self.write(chapter=True)
self.assertIn('metadata-mismatch', self.codes())
def test_missing_and_extra_verses(self):
self.write({'2': {'text': '神が創造した。'}})
self.assertEqual(self.codes(), {'missing-verse', 'extra-verse'})
def test_empty_and_bad_number(self):
self.write({'1': {'text': ''}, '02': {'text': '日本語'}})
self.assertTrue({'invalid-text', 'invalid-verse-number', 'missing-verse'} <= self.codes())
def test_extra_chapter_and_duplicate_alias(self):
path = self.write()
(path.parent / 'chapter_001.json').write_bytes(path.read_bytes())
self.assertTrue({'duplicate-chapter', 'duplicate-verse', 'noncanonical-filename'} <= self.codes())
(path.parent / 'chapter_02.json').write_bytes(path.read_bytes())
self.assertIn('unexpected-chapter', self.codes())
def test_text_hazards_and_stale_ruby(self):
self.write({'1': {'text': '神\n\ufffd', 'text_with_furigana': '別の文'}})
self.assertTrue({'control-character', 'invalid-plain-text', 'furigana-mismatch'} <= self.codes())
def test_unexpected_files(self):
self.write()
(self.root / 'unknown').mkdir()
self.assertIn('unexpected-path', self.codes())
def test_review_flags(self):
rows = {('genesis', 1, 1): '翻訳結果 TODO λ', ('genesis', 1, 2): '翻訳結果 TODO λ'}
queue = list(review.review(rows, self.baseline))
self.assertEqual(len(queue), 2)
self.assertTrue({'latin-text', 'source-script', 'identical-within-chapter',
'placeholder-or-commentary'} <= set(queue[0]['flags'].split(';')))
def test_book_aliases(self):
self.assertEqual(verify.book_id('III John'), '3john')
self.assertEqual(verify.book_id('Revelation of John'), 'revelation')
self.assertEqual(verify.book_id('song_of_solomon'), 'songofsolomon')
if __name__ == '__main__':
unittest.main()