import unittest from textbook.build_database import build, decl_name, split_prelude, statement_identifiers ENTRIES = [ {"id": "goodman-1-6-1", "source_label": "Proposition 1.6.1", "kind": "proposition", "statement": "\u2200 (a : \u2124), 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": "\u2200 (as : List \u2124), IsGCDOfList 1 as", "prelude": "import Mathlib\ndef IsGCDOfList (d : \u2115) (as : List \u2124) : Prop := True", "natural_language": "", "requires": [], "elaborates": True}, {"id": "goodman-1-6-99", "source_label": "Proposition 1.6.99", "kind": "proposition", "statement": "\u2200 (as : List \u2124), IsGCDOfList 2 as", "prelude": "import Mathlib\ndef IsGCDOfList (d : \u2115) (as : List \u2124) : Prop := True", "natural_language": "", "requires": [], "elaborates": True}, ] class BuildDatabaseTests(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_unproven_entries_become_axioms(self): text, index, emitted, skipped = build(ENTRIES) self.assertIn('axiom goodman_1_6_1 :', text) self.assertEqual(len(emitted), 3) self.assertEqual(skipped, []) self.assertTrue(all(r['status'] == 'asserted' for r in index)) 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, index, _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) statuses = {r['id']: r['status'] for r in index} self.assertEqual(statuses['goodman-1-6-1'], 'proved') self.assertEqual(statuses['goodman-1-6-24'], 'asserted') 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, _index, _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, index, emitted, skipped = build(entries, require_checked=True) self.assertEqual(emitted, ['goodman-1-6-1']) self.assertEqual(skipped, ['goodman-1-6-24']) self.assertEqual(len(index), 1) def test_recorded_proof_counts_only_once_checked(self): # An unverified proof must NOT be emitted as a theorem -- the library may # never claim more than Lean has confirmed. pending = [dict(ENTRIES[0], proof='ring', proof_checked=False)] text, index, _e, _s = build(pending) self.assertIn('axiom goodman_1_6_1 :', text) self.assertNotIn('theorem goodman_1_6_1 :', text) self.assertEqual(index[0]['status'], 'proof_pending') self.assertEqual(index[0]['proof'], 'ring') checked = [dict(ENTRIES[0], proof='ring', proof_checked=True)] text, index, _e, _s = build(checked) self.assertIn('theorem goodman_1_6_1 :', text) self.assertIn(' ring', text) self.assertEqual(index[0]['status'], 'proved') def test_index_carries_identifiers_and_strips_fix_notes(self): _text, index, _emitted, _skipped = build(ENTRIES) first = index[0] self.assertIn('Int.add_zero', first['requires']) self.assertNotIn('fix note', first['natural_language']) self.assertNotIn('let', statement_identifiers('let x := 1')) if __name__ == '__main__': unittest.main()