import unittest from textbook.build_database import build, decl_name, resolve_proof, split_prelude, statement_identifiers ENTRIES = [ {"id": "goodman-1-6-1", "source_label": "Proposition 1.6.1", "kind": "proposition", "statement": "∀ (a : ℤ), a + 0 = a", "prelude": "import Mathlib", "natural_language": "Zero is an additive identity. [fix note: irrelevant]", "requires": ["Int.add_zero"], "elaborates": True}, {"id": "goodman-1-6-24", "source_label": "Proposition 1.6.24", "kind": "proposition", "statement": "∀ (as : List ℤ), IsGCDOfList 1 as", "prelude": "import Mathlib\ndef IsGCDOfList (d : ℕ) (as : List ℤ) : Prop := True", "natural_language": "", "requires": [], "elaborates": True}, {"id": "goodman-1-6-99", "source_label": "Proposition 1.6.99", "kind": "proposition", "statement": "∀ (as : List ℤ), IsGCDOfList 2 as", "prelude": "import Mathlib\ndef IsGCDOfList (d : ℕ) (as : List ℤ) : Prop := True", "natural_language": "", "requires": [], "elaborates": True}, ] class HelperTests(unittest.TestCase): def test_decl_name_is_a_legal_lean_identifier(self): self.assertEqual(decl_name('goodman-1-6-2-a'), 'goodman_1_6_2_a') def test_split_prelude_separates_imports_from_defs(self): imports, other = split_prelude('import Mathlib\ndef Foo := True') self.assertEqual(imports, ['import Mathlib']) self.assertEqual(other, 'def Foo := True') def test_statement_identifiers_skips_stopwords(self): self.assertNotIn('let', statement_identifiers('let x := 1')) self.assertIn('Nat.Prime', statement_identifiers('Nat.Prime p')) class ResolveProofTests(unittest.TestCase): """A proof only counts once Lean has verified it -- this is the gate that keeps the library from claiming more than was actually checked.""" def test_no_proof_is_asserted(self): self.assertEqual(resolve_proof({"id": "x"}), (None, 'asserted')) def test_unverified_proof_is_pending_not_proved(self): proof, status = resolve_proof({"id": "x", "proof": "ring", "proof_checked": False}) self.assertEqual(status, 'proof_pending') self.assertIsNone(proof) def test_verified_proof_is_proved(self): proof, status = resolve_proof({"id": "x", "proof": "ring", "proof_checked": True}) self.assertEqual((proof, status), ('ring', 'proved')) def test_successful_bench_run_proves_an_entry_with_no_recorded_proof(self): result = {"success": True, "attempts": [{"proof": "simp"}]} self.assertEqual(resolve_proof({"id": "x"}, result), ('simp', 'proved')) def test_failed_bench_run_does_not_prove(self): result = {"success": False, "attempts": []} self.assertEqual(resolve_proof({"id": "x"}, result), (None, 'asserted')) class BuildDatabaseTests(unittest.TestCase): def test_unproven_entries_become_axioms(self): text, emitted, skipped = build(ENTRIES) self.assertIn('axiom goodman_1_6_1 :', text) self.assertNotIn('theorem goodman_1_6_1 :', text) self.assertEqual(len(emitted), 3) self.assertEqual(skipped, []) def test_proven_entries_become_real_theorems_with_their_proof(self): results = {"goodman-1-6-1": {"id": "goodman-1-6-1", "success": True, "attempts": [{"proof": "simp"}]}} text, _emitted, _skipped = build(ENTRIES, results) self.assertIn('theorem goodman_1_6_1 :', text) self.assertNotIn('axiom goodman_1_6_1 :', text) self.assertIn(' simp', text) self.assertIn('Proof verified by Lean.', text) def test_recorded_proof_is_only_emitted_once_checked(self): pending = [dict(ENTRIES[0], proof='ring', proof_checked=False)] text, _e, _s = build(pending) self.assertIn('axiom goodman_1_6_1 :', text) self.assertIn('not yet verified', text) checked = [dict(ENTRIES[0], proof='ring', proof_checked=True)] text, _e, _s = build(checked) self.assertIn('theorem goodman_1_6_1 :', text) self.assertIn(' ring', text) def test_shared_def_in_prelude_is_emitted_once_not_per_entry(self): # Two entries share the same `def`; declaring it twice in one Lean file is an # "already declared" error, so it must be hoisted and deduplicated. text, _emitted, _skipped = build(ENTRIES) self.assertEqual(text.count('def IsGCDOfList'), 1) self.assertEqual(text.count('import Mathlib'), 1) def test_require_checked_skips_unverified_entries(self): entries = [dict(ENTRIES[0]), dict(ENTRIES[1], elaborates=False)] text, emitted, skipped = build(entries, require_checked=True) self.assertEqual(emitted, ['goodman-1-6-1']) self.assertEqual(skipped, ['goodman-1-6-24']) self.assertNotIn('goodman_1_6_24', text) def test_docstring_records_provenance_and_axiom_warning(self): text, _emitted, _skipped = build(ENTRIES) self.assertIn('Proposition 1.6.1', text) self.assertIn('ASSERTED from the textbook', text) self.assertNotIn('fix note', text) if __name__ == '__main__': unittest.main()