Files
paper-atlas/tests/test_iclr.py
T
codex-bot 1c18cbe03a
Metadata integrity checks / metadata (push) Successful in 1m12s
Package Paper Atlas with organized modules and a unified CLI
2026-11-06 17:32:24 +08:00

99 lines
6.5 KiB
Python

import json
from pathlib import Path
import tempfile
import unittest
from unittest.mock import patch
from urllib.error import HTTPError
from paper_atlas.collectors.iclr import asset_urls, collect_year, discover, parse_program
from paper_atlas.ingestion.records import ingest_file
from paper_atlas.db.store import Store
class ICLRTests(unittest.TestCase):
def event(self,identifier=1,sourceid=10,**updates):
row={'id':identifier,'sourceid':sourceid,'sourceurl':'https://openreview.net/group?id=ICLR.cc/2026/Conference',
'name':'A reliable paper on abstract metadata indexing','authors':[{'fullname':'Jane Doe'},{'fullname':'John Smith'}],
'eventtype':'Poster','event_type':'Poster','decision':'Accept (Oral)',
'paper_url':'https://openreview.net/forum?id=realForum','topic':'Learning->Theory','keywords':[]}
return dict(row,**updates)
def parse(self,events,abstracts=None,year=2026):
return parse_program({'count':len(events),'next':None,'previous':None,'results':events},abstracts or {},year,f'https://iclr.cc/virtual/{year}/papers.html')
def test_oral_placeholder_is_not_an_identifier_or_another_submission(self):
poster=self.event()
oral=self.event(2,-10,eventtype='Oral',event_type='Oral',paper_url='https://openreview.net/forum?id=2026-Oral--10-placeholder')
rows,audit=self.parse([oral,poster],{'1':'The real abstract.'})
self.assertEqual(len(rows),1)
self.assertEqual(rows[0]['identifiers'],{'openreview':'realForum'})
self.assertEqual(rows[0]['abstract'],'The real abstract.')
self.assertEqual(rows[0]['metadata']['presentation_types'],['Oral','Poster'])
self.assertEqual(audit['main_event_count'],2)
def test_blog_and_journal_presentations_are_not_main_acceptances(self):
rows,audit=self.parse([self.event(),self.event(2,20,sourceurl='https://openreview.net/group?id=ICLR.cc/2026/BlogPosts'),self.event(3,30,sourceurl='2026-TMLR-J2C-Spreadsheet')])
self.assertEqual(len(rows),1)
self.assertEqual(sum(audit['excluded_events_by_source'].values()),2)
self.assertEqual(audit['missing_abstract_count'],1)
self.assertIsNone(rows[0]['abstract'])
def test_title_revision_is_scoped_to_matching_signed_submission_and_authors(self):
poster=self.event(name='AlphaEdit: Null-Space Constrained Knowledge Editing for Language Models')
oral=self.event(2,-10,eventtype='Oral',name='AlphaEdit: Null-Space Constrained Model Editing for Language Models')
rows,_=self.parse([oral,poster])
self.assertEqual(len(rows),1)
self.assertEqual(rows[0]['title'],poster['name'])
self.assertEqual(len(rows[0]['metadata']['presentation_titles']),2)
with self.assertRaisesRegex(ValueError,'collides'):
self.parse([poster,dict(oral,authors=[{'fullname':'Unrelated Author'}])])
def test_truncation_and_identity_collision_fail(self):
with self.assertRaisesRegex(ValueError,'count differs'):
parse_program({'count':2,'results':[self.event()]},{},2026,'https://iclr.cc/')
with self.assertRaisesRegex(ValueError,'collides'):
self.parse([self.event(),self.event(2,-10,name='A different paper')])
with self.assertRaisesRegex(ValueError,'Conflicting identifiers'):
self.parse([self.event(),self.event(2,10,paper_url='https://openreview.net/forum?id=otherForum')])
def test_legacy_embedded_abstracts_and_paper_links(self):
row=self.event(sourceurl=None,abstract='Historical abstract',paper_url=None,paper_pdf_url='https://openreview.net/forum?id=historicalForum',decision='Poster')
rows,_=self.parse([row],year=2021)
self.assertEqual(rows[0]['abstract'],'Historical abstract')
self.assertEqual(rows[0]['identifiers'],{'openreview':'historicalForum'})
rows,_=self.parse([dict(row,paper_pdf_url=None)],year=2020)
self.assertEqual(rows[0]['metadata']['identity_state'],'program_only')
self.assertEqual(rows[0]['identifiers'],{})
def test_only_referenced_official_assets_and_real_navigation_years(self):
html='<a href="/archive/2013/">2013</a><a href="/Conferences/2026">2026</a><a href="https://other.example/2025">2025</a>'
self.assertEqual([y for y,_ in discover(html)],[2013,2026])
html='start("/static/virtual/data/iclr-2026-orals-posters.json",true,"https://other.example/abstracts.json")'
self.assertEqual(asset_urls(html,'https://iclr.cc/virtual/2026/papers.html',2026),{'orals-posters':'https://iclr.cc/static/virtual/data/iclr-2026-orals-posters.json'})
def test_missing_split_abstract_asset_does_not_discard_embedded_abstract(self):
html=b'start("/static/virtual/data/iclr-2021-orals-posters.json",true,"/static/virtual/data/iclr-2021-abstracts.json")'
event=self.event(sourceurl=None,decision='Poster',abstract='Embedded historical abstract')
responses=[html,json.dumps({'count':1,'results':[event]}).encode(),HTTPError('https://iclr.cc/abstracts',404,'Not Found',None,None)]
with tempfile.TemporaryDirectory() as tmp,patch('paper_atlas.collectors.iclr.fetch',side_effect=responses):
manifest=collect_year(2021,tmp,tmp)
self.assertEqual(manifest['status'],'collected')
self.assertEqual(manifest['missing_abstract_count'],0)
self.assertEqual(manifest['abstract_asset_status'],'unavailable_404')
def test_import_repeat_preserves_one_submission_and_queryable_platform_tags(self):
rows,_=self.parse([self.event(),self.event(2,-10,eventtype='Oral')],{'1':'A searchable abstract.'})
with tempfile.TemporaryDirectory() as tmp:
path=Path(tmp)/'iclr.jsonl';db=Path(tmp)/'papers.sqlite'
path.write_text(''.join(json.dumps(r)+'\n' for r in rows))
path.with_suffix('.manifest.json').write_text(json.dumps({'source':'iclr_program','parser_version':2,'list_url':'https://iclr.cc/virtual/2026/papers.html','count':1,'status':'collected'}))
ingest_file(db,path);ingest_file(db,path)
store=Store(db);self.addCleanup(store.conn.close)
self.assertEqual(store.conn.execute('SELECT count(*) FROM submissions').fetchone()[0],1)
self.assertEqual(store.conn.execute('SELECT count(*) FROM decisions').fetchone()[0],1)
self.assertEqual(store.conn.execute('SELECT namespace,value FROM tags').fetchall(),[('iclr_program:topic','Learning->Theory')])
self.assertEqual(store.conn.execute('PRAGMA foreign_key_check').fetchall(),[])
if __name__=='__main__':unittest.main()