tricu

An interpreted language for exploring Tree Calculus
Log | Files | Refs | README | LICENSE

io_v2_zig_stages.py (3731B)


      1 #!/usr/bin/env python3
      2 """Cross-directory publication, EXDEV, invalid destinations and no rollback."""
      3 import argparse
      4 import hashlib
      5 import json
      6 import subprocess
      7 import tempfile
      8 from pathlib import Path
      9 from source_order import Runner
     10 from http_headers import result,tree_list,number
     11 from process_rss import run_guarded
     12 ROOT=Path(__file__).resolve().parent.parent
     13 
     14 def text(s):return tree_list([number(ord(c)) for c in str(s)])
     15 def main():
     16     p=argparse.ArgumentParser(description=__doc__);p.add_argument('tricu',type=Path);p.add_argument('probe',type=Path);p.add_argument('--directory',type=Path,required=True)
     17     args=p.parse_args();d=args.directory.resolve();d.mkdir(parents=True,exist_ok=False);r=Runner(args.tricu,d);bundle=d/'stages.arboricx'
     18     r.run('compile',['compile','--file',ROOT/'test/io-v2/zig-stages.tri','--store',r.store,'--output',bundle]);pin=r.imported(bundle,'import');checks=[]
     19     a,b=d/'a',d/'b';a.mkdir();b.mkdir();target=b/'published'
     20     def invoke(name,values,label,expected):
     21         command=[str(args.probe.resolve()),str(bundle),name,*[str(v) if isinstance(v,int) else 'text:'+str(v) for v in values]]
     22         output,peak=run_guarded(command,memory_mib=128,seconds=60);(d/(label+'.log')).write_text(output)
     23         assert bytes(map(int,output.strip()))==expected,label
     24         checks.append(dict(label=label,peak_kib=peak))
     25     for mode,state in [(0,'published'),(0,'exists'),(1,'published')]:
     26         invoke('publish',[a,target,mode],f'publish-{mode}-{state}',result(True,text(state)))
     27         assert target.read_bytes()==b'abc' and list(a.iterdir())==[]
     28     target.unlink()  # prove visibility was created before the terminal failure
     29     process=subprocess.run([str(args.probe.resolve()),str(bundle),'failureAfterPublication','text:'+str(a),'text:'+str(target)],capture_output=True,timeout=60)
     30     assert process.returncode==1 and b'failed (payload not forced)' in process.stderr
     31     assert target.read_bytes()==b'abc' and list(a.iterdir())==[];checks.append(dict(label='no-rollback-after-failure'))
     32     for name in ('.tricu-stage-protected','x.tricu-stage-protected'):
     33         bad=b/name
     34         expected=tree_list([result(False,tree_list([text('invalid-destination'),text('stage/publish'),text('destination must name a file outside the private staging namespace'),text('not-published')])),result(False,tree_list([text('invalid-state'),text('stage/publish'),text('stage is not in the required phase'),text('none')]))])
     35         invoke('invalidDestination',[a,bad],name,expected)
     36         assert not bad.exists() and list(a.iterdir())==[]
     37     # Do not manufacture EXDEV through a mock here: require a distinct device.
     38     with tempfile.TemporaryDirectory(prefix='tricu-zig-exdev-',dir='/dev/shm') as foreign:
     39         foreign=Path(foreign)
     40         assert foreign.stat().st_dev != a.stat().st_dev,'EXDEV control needs distinct filesystems'
     41         output=foreign/'out'
     42         expected=tree_list([tree_list([text('io-error'),text('unknown')]),tree_list([text('invalid-state'),text('none')])])
     43         invoke('crossDevice',[a,output],'actual-exdev',expected)
     44         assert not output.exists() and list(a.iterdir())==[]
     45         flags=['--io']
     46         for i,v in enumerate((a,output)):
     47             arg=d/f'exdev-{i}.tree';arg.write_bytes(text(v));flags+=['--arg-tree-file',arg]
     48         assert r.invoke('exdev-haskell',pin,'crossDevice',flags)==expected
     49         assert not output.exists() and list(a.iterdir())==[]
     50     (d/'report.json').write_text(json.dumps(dict(checks=checks,haskell=r.records,probe_sha256=hashlib.sha256(args.probe.read_bytes()).hexdigest()),indent=2)+'\n')
     51     print(f'PASS {len(checks)} private staged-publication controls including real EXDEV')
     52 if __name__=='__main__':main()