"""Publisher evidence, section boundaries and native-ingestion regression checks.""" import hashlib import json import re from pathlib import Path import sqlite3 import tempfile import unittest from unittest.mock import patch from paper_atlas.collectors import aamas from paper_atlas.ingestion.records import ingest_file def paper(pid, abstract=True): summary = 'Research with evidence.
More detail.
' if abstract else '' return f'''
{pid}

{summary} A structured & auditable paper {pid} Jane Doehas 7 papers, Bob Smith

''' def page(section, pid, abstract=True): heading = aamas.SECTIONS[section][0] return (f'{heading} - AAMAS 2012' f'

{heading}

Session 1A – Robotics I

' +paper(pid, abstract)+'') class AamasProceedingsTests(unittest.TestCase): def snapshots(self, root): root.mkdir() receipts = [] items = {'introduction': ('AAMAS 2012

Aggregate withdrawals do not identify papers.

', aamas.ROOT)} for index, section in enumerate(aamas.SECTIONS): items[section] = (page(section, f'P{index}_1', section != 'extabstracts'), aamas.ROOT+'resources/'+section+'.html') for key, (html, url) in items.items(): data = html.encode() (root/(key+'.html')).write_bytes(data) receipts.append({'url': url, 'status': 200, 'file': key+'.html', 'bytes': len(data), 'sha256': hashlib.sha256(data).hexdigest(), 'finished_at': '2026-11-09T00:00:00+00:00'}) (root/'receipts.json').write_text(json.dumps({'receipts': receipts})) return root def test_hidden_abstract_and_author_badges_are_not_title_or_authors(self): rows = aamas.parse_section(page('fullpapers', '1A_1'), 'fullpapers', '2026-11-09T00:00:00Z', {'sha256': 'proof'}) row, = rows self.assertEqual(row['title'], 'A structured & auditable paper 1A_1') self.assertEqual(row['abstract'], 'Research with evidence. More detail.') self.assertEqual(row['authors'], ['Jane Doe', 'Bob Smith']) self.assertEqual(row['metadata']['authors_display'], 'Jane Doe, Bob Smith') self.assertEqual(row['url'], aamas.ROOT+'resources/fullpapers.html#1A_1') self.assertEqual(row['metadata']['paper_url'], aamas.ROOT+'papers/1A_1.pdf') self.assertEqual(row['metadata']['source_evidence'], {'sha256': 'proof'}) def test_publication_formats_and_session_topics_do_not_invent_submission_tracks(self): for section, (_, fmt, track, _) in aamas.SECTIONS.items(): row, = aamas.parse_section(page(section, 'P_1', False), section, '2026-11-09T00:00:00Z', {}) self.assertEqual((row['track'], row['metadata']['publication_format']), (track, fmt)) self.assertIsNone(row['abstract']) self.assertEqual(row['status'], 'accepted') self.assertEqual(row['metadata']['decision_date_precision'], 'not_supplied') self.assertEqual(row['metadata']['session']['title'], 'Session 1A – Robotics I') self.assertIn({'namespace': 'aamas_proceedings:publication_format', 'value': fmt}, row['tags']) self.assertEqual(aamas.SECTIONS['fullpapers'][2], 'proceedings_unspecified') self.assertEqual(aamas.SECTIONS['extabstracts'][2], 'proceedings_unspecified') def test_changed_edition_section_duplicate_id_or_pdf_link_is_rejected(self): html = page('fullpapers', '1A_1') for changed in [html.replace('AAMAS 2012', 'AAMAS 2025'), html.replace('

Full Papers

', '

Rejected Papers

'), html.replace('', paper('1A_1')+''), html.replace('../papers/1A_1.pdf', 'https://example.org/1A_1.pdf'), html.replace('../papers/1A_1.pdf', '../papers/1A_2.pdf')]: with self.subTest(changed=changed): with self.assertRaises(ValueError): aamas.parse_section(changed, 'fullpapers', '2026-11-09T00:00:00Z', {}) def test_frozen_responses_require_checksums_success_and_safe_paths(self): for failure in ['checksum', 'status', 'path']: with self.subTest(failure=failure), tempfile.TemporaryDirectory() as temporary: root = self.snapshots(Path(temporary)/'source') path = root/'receipts.json' receipts = json.loads(path.read_text()) item = receipts['receipts'][0] if failure == 'checksum': item['sha256'] = '0'*64 elif failure == 'status': item['status'] = 404 else: item['file'] = '../outside.html' path.write_text(json.dumps(receipts)) with self.assertRaises(ValueError): aamas.read_pages(snapshots=root) def test_reviewed_section_counts_and_year_are_required(self): with tempfile.TemporaryDirectory() as temporary: root = Path(temporary) source = self.snapshots(root/'source') with self.assertRaises(ValueError): aamas.collect(2012, root/'out', snapshots=source) self.assertFalse((root/'out/aamas-proceedings-2012.json').exists()) with self.assertRaises(ValueError): aamas.collect(2026, root/'future', snapshots=source) self.assertFalse((root/'future').exists()) def test_ids_colliding_across_sections_do_not_produce_a_completed_collection(self): with tempfile.TemporaryDirectory() as temporary: root = Path(temporary) source = self.snapshots(root/'source') receipts_path = source/'receipts.json' receipts = json.loads(receipts_path.read_text()) for item in receipts['receipts'][1:]: path = source/item['file'] data = re.sub(r'P[0-9]_1', 'SAME_1', path.read_text()).encode() path.write_bytes(data) item.update(bytes=len(data), sha256=hashlib.sha256(data).hexdigest()) receipts_path.write_text(json.dumps(receipts)) small = {key: (*value[:3], 1) for key, value in aamas.SECTIONS.items()} with patch.dict(aamas.SECTIONS, small, clear=True), self.assertRaises(ValueError): aamas.collect(2012, root/'out', snapshots=source) self.assertFalse((root/'out/aamas-proceedings-2012.json').exists()) def test_collection_and_native_ingestion_preserve_formats_evidence_and_missing_abstracts(self): with tempfile.TemporaryDirectory() as temporary: root = Path(temporary) source = self.snapshots(root/'source') small = {key: (*value[:3], 1) for key, value in aamas.SECTIONS.items()} with patch.dict(aamas.SECTIONS, small, clear=True): result = aamas.collect(2012, root/'out', snapshots=source) self.assertEqual(result['records'], 4) self.assertEqual(len(result['files']), 3) self.assertFalse(result['database_written']) self.assertFalse(result['pdfs_downloaded']) db = root/'sample.sqlite' for manifest in result['files']: path = Path(manifest['file']) self.assertEqual(hashlib.sha256(path.read_bytes()).hexdigest(), manifest['file_sha256']) for raw in path.read_text().splitlines(): record = json.loads(raw) evidence = record['metadata']['source_evidence'] self.assertEqual(hashlib.sha256((root/'out'/evidence['file']).read_bytes()).hexdigest(), evidence['sha256']) ingest_file(db, path) with sqlite3.connect(db) as connection: self.assertEqual(connection.execute('SELECT count(*) FROM papers').fetchone()[0], 4) self.assertEqual(connection.execute('SELECT count(*) FROM submissions').fetchone()[0], 4) self.assertEqual(connection.execute("SELECT count(*) FROM decisions WHERE status='accepted'").fetchone()[0], 4) self.assertEqual(connection.execute('SELECT count(*) FROM papers WHERE abstract IS NULL').fetchone()[0], 1) metadata = [json.loads(r[0]) for r in connection.execute('SELECT metadata_json FROM source_records')] self.assertEqual({r['publication_format'] for r in metadata}, {'full_paper','extended_abstract','demo','doctoral_abstract'}) namespaces = {r[0] for r in connection.execute('SELECT DISTINCT namespace FROM tags')} self.assertEqual(namespaces, {'aamas_proceedings:publication_format', 'aamas_proceedings:session'}) self.assertEqual(connection.execute('PRAGMA foreign_key_check').fetchall(), [])