import unittest from textbook.check_proofs import ALLOWED_AXIOMS, AXIOM_LINE, check_proof class CheckProofsTests(unittest.TestCase): """Only the Lean-free logic is unit-tested here; actually compiling a proof needs Lean and Mathlib, which is what running check_proofs.py on a real machine does.""" def test_missing_proof_fails_without_invoking_lean(self): result = check_proof('t', 'True', '') self.assertFalse(result.ok) self.assertIn('no proof recorded', result.diagnostics) def test_sorry_is_rejected_without_invoking_lean(self): for escape in ('sorry', 'admit', 'native_decide'): result = check_proof('t', 'True', f'intro h\n{escape}') self.assertFalse(result.ok, escape) self.assertIn(escape, result.diagnostics) def test_proof_mentioning_sorry_only_as_substring_is_not_rejected_for_that(self): # 'sorryAx' contains 'sorry' but \b...\b must not match a longer identifier, # otherwise a legitimate name would be banned by accident. from textbook.check_proofs import BANNED self.assertIsNone(BANNED.search('exact notsorryreally')) self.assertIsNotNone(BANNED.search('exact sorry')) def test_axiom_line_parsing_separates_standard_from_ours(self): line = "'goodman_1_6_1' depends on axioms: [propext, Classical.choice, Quot.sound]" used = {a.strip() for a in AXIOM_LINE.search(line).group(1).split(',')} self.assertEqual(used - ALLOWED_AXIOMS, set()) def test_axiom_line_parsing_flags_a_book_asserted_axiom(self): line = "'x' depends on axioms: [propext, goodman_1_6_7, sorryAx]" used = {a.strip() for a in AXIOM_LINE.search(line).group(1).split(',')} self.assertEqual(used - ALLOWED_AXIOMS, {'goodman_1_6_7', 'sorryAx'}) if __name__ == '__main__': unittest.main()