"""SQLite update fixture with HTTP-like outcomes, not an HTTP server/parser.""" import json import re import sqlite3 from pathlib import Path ROOT = Path(__file__).parent db = sqlite3.connect(':memory:', isolation_level=None) db.execute('CREATE TABLE document (id TEXT PRIMARY KEY, title TEXT, revision INTEGER)') db.execute("INSERT INTO document VALUES ('d1', 'Original', 1)") snapshots = [db.execute("SELECT revision FROM document WHERE id='d1'").fetchone()[0] for _ in range(2)] # Both application-level comparisons see the same revision before either write. assert snapshots == [1,1] db.execute("UPDATE document SET title='A', revision=revision+1 WHERE id='d1'") db.execute("UPDATE document SET title='B', revision=revision+1 WHERE id='d1'") unsafe = db.execute("SELECT title, revision FROM document WHERE id='d1'").fetchone() assert unsafe == ('B',3) db.execute("UPDATE document SET title='Original', revision=1 WHERE id='d1'") def update(resource, header, value): if header is None: return 428 if header == '*': changed=db.execute('UPDATE document SET title=?, revision=revision+1 WHERE id=?',(value,resource)).rowcount else: # Fixture accepts one generated tag only, not the full HTTP list grammar. match=re.fullmatch(r'"v([1-9][0-9]*)"',header) if not match: if header.startswith('W/'): return 412 raise ValueError('Input outside the narrow fixture grammar') changed=db.execute('UPDATE document SET title=?, revision=revision+1 WHERE id=? AND revision=?',(value,resource,int(match[1]))).rowcount return 204 if changed == 1 else 412 cases=[('client A','d1','"v1"','A',204),('stale client B','d1','"v1"','B',412),('weak current tag','d1','W/"v2"','Weak',412),('missing precondition','d1',None,'Missing',428),('wildcard existing','d1','*','Wildcard',204),('wildcard absent','absent','*','No row',412),('reread and merge','d1','"v3"','Reviewed merge',204)] rows=[] for label,resource,tag,value,expected in cases: status=update(resource,tag,value) assert status==expected,(label,status) title,revision=db.execute("SELECT title,revision FROM document WHERE id='d1'").fetchone() rows.append(dict(case=label,if_match=tag,status=status,title_after=title,revision_after=revision)) assert rows[1]['title_after']=='A' and rows[1]['revision_after']==2 assert rows[-1]['title_after']=='Reviewed merge' and rows[-1]['revision_after']==4 data={'sqlite_version':sqlite3.sqlite_version,'unsafe_final':{'title':unsafe[0],'revision':unsafe[1]},'guarded_cases':rows,'writes':sum(x['status']==204 for x in rows),'rejected':sum(x['status']!=204 for x in rows)} (ROOT/'results.json').write_text(json.dumps(data,indent=2)+'\n') print(json.dumps(data,indent=2))