io_clock.py (3258B)
1 #!/usr/bin/env python3 2 """Actual source timing, scoped waits/cancellation, and migrated async demos.""" 3 import argparse 4 import json 5 from pathlib import Path 6 import subprocess 7 from source_order import Runner 8 from http_headers import number, result, tree_list 9 from io_objects import text 10 from io_directory import parse_tree, natural 11 12 ROOT=Path(__file__).resolve().parent.parent 13 14 def main(): 15 p=argparse.ArgumentParser(description=__doc__) 16 p.add_argument('tricu',type=Path);p.add_argument('--directory',type=Path,required=True) 17 a=p.parse_args();root=a.directory.resolve();root.mkdir(parents=True,exist_ok=False) 18 runner=Runner(a.tricu,root);checks=[] 19 def compile(label,path): 20 bundle=root/(label+'.arboricx') 21 runner.run(label+'-compile',['compile','--file',path,'--store',runner.store,'--output',bundle,'--compile-timeout','600'],seconds=660) 22 return runner.imported(bundle,label+'-import') 23 pin=compile('clock',ROOT/'demos/io/clock.tri') 24 def invoke(label,name,value=None): 25 args=['--io'] 26 if value is not None: 27 path=root/(label+'.tree');path.write_bytes(value);args+=['--arg-tree-file',path] 28 return runner.invoke(label,pin,name,args) 29 assert invoke('yield','yielded')==result(True,b'\0');checks.append('yield-unit') 30 assert invoke('cancelled','cancelledWait')==tree_list([text('cancelled'),text('timer-stop'),b'\0']);checks.append('cancel-max-duration') 31 for milliseconds in [0,1,20]: 32 raw=invoke(f'elapsed-{milliseconds}','elapsed',number(milliseconds)) 33 # Decode the binary kernel tree with the existing reader; compare to an 34 # independent host duration bound, never a self-derived expected value. 35 elapsed=natural(parse_tree(raw)) 36 assert elapsed>=milliseconds*1000000,(milliseconds,elapsed) 37 checks.append(f'elapsed-{milliseconds}') 38 assert natural(parse_tree(invoke('scope-wait','scopeWait')))>=20000000 39 checks.append('normal-scope-waits') 40 problem=tree_list([text('invalid-argument'),text('clock/sleep'),b'\0',text('none')]) 41 for i,value in enumerate([number(9223372036854775808),b'\1\0',b'\2\0\0']): 42 assert invoke(f'invalid-{i}','invalidSleep',value)==result(False,problem) 43 checks.append(f'invalid-{i}') 44 for label,path,wanted in [ 45 ('async',ROOT/'demos/interactionTrees.tri',b'Parent first!\n2000ms done sleeping!\n5000ms done sleeping!\n'), 46 ('yield-demo',ROOT/'demos/interactionTrees/yield.tri',b'A says 1\nA says 2\nA says 3\nB says 1\nB says 2\nB says 3\nFinished: doneA doneB\n')]: 47 demo=compile(label,path) 48 command=[str(runner.exe),'arboricx','run','--module',demo,'--name','main','--store',str(runner.store),'--io','--no-result'] 49 run=subprocess.run(command,stdout=subprocess.PIPE,stderr=subprocess.PIPE,timeout=30) 50 (root/(label+'.stdout')).write_bytes(run.stdout);(root/(label+'.stderr')).write_bytes(run.stderr) 51 assert run.returncode==0,(label,run.stderr) 52 assert run.stdout==wanted,(label,run.stdout) 53 checks.append(label) 54 (root/'report.json').write_text(json.dumps(dict(passed=checks,records=runner.records),indent=2)+'\n') 55 print(f'PASS {len(checks)} clock/caller controls') 56 if __name__=='__main__':main()