tricu

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

scp_native_validation.py (5569B)


      1 #!/usr/bin/env python3
      2 """Focused Haskell-only SCP artifacts, lessons and prepared deployments."""
      3 import argparse
      4 from pathlib import Path
      5 import re
      6 import shutil
      7 from research_session import ResearchSession, ROOT
      8 
      9 p = argparse.ArgumentParser(description=__doc__)
     10 p.add_argument('tricu', type=Path)
     11 p.add_argument('--directory', type=Path, required=True)
     12 p.add_argument('--projects-only', action='store_true')
     13 p.add_argument('--include-self-size', action='store_true', help='explicit expensive logical-tree self-size observation')
     14 args = p.parse_args()
     15 # No compiler authoring/preparation job: only import the checked full artifacts.
     16 s = ResearchSession.__new__(ResearchSession)
     17 s.tricu, s.root = str(args.tricu.resolve()), args.directory.resolve()
     18 s.root.mkdir(parents=True, exist_ok=True)
     19 s.store, s.events = s.root / 'cas', []
     20 s.memory_mib = 8192
     21 import time
     22 s.deadline = time.monotonic() + 1180
     23 bootstrap = s.root / 'bootstrap'; bootstrap.mkdir(exist_ok=True)
     24 for source, target in [('compiler-library.arboricx','compiler-bootstrap.arboricx'),
     25                        ('support-library.arboricx','scp-bootstrap.arboricx')]:
     26     shutil.copyfile(ROOT / 'test/fixtures' / source, bootstrap / target)
     27 output, _ = s.run([s.tricu,'arboricx','import','--store',s.store,
     28                   '--file',bootstrap/'scp-bootstrap.arboricx','--indexed'])
     29 pin = re.search(rb'Created module alias .* -> ([0-9a-f]{64})', output)[1].decode()
     30 lessons = {
     31     'equality': [b'same representation: same',b'two identities: different',b'result on Leaf: same',b'result on Fork: same'],
     32     'size': [b'Leaf: 1',b'Stem Leaf: 2',b'Fork Leaf Leaf: 3',b'Compiled worker itself: '],
     33     'patterns': [b'Leaf: Leaf',b'Stem Leaf: Stem Leaf',b'Stem Fork: Stem of Fork',b'Stem Stem: Stem of something else',b'Fork: Fork'],
     34     'source': [b'Leaf: t',b'Stem Leaf: (t t)',b'Fork Leaf Leaf: (t t t)',b'Identity function: (t ',b'String a as a tree: (t '],
     35 }
     36 cases = [('fizzbuzz_lambda', False, [b'lambda-baseline-ok']),
     37          ('fizzbuzz_structural', False, [b'consumer-spike-ok']),
     38          ('layout_layout', False, [b'layout-consumer-ok']),
     39          ('collect_prefixes_collect_prefixes', True, [b'matches=3',b'first=item',b'unmatched-first=none'])]
     40 for name, expected in lessons.items():
     41     if name == 'size' and not args.include_self_size:
     42         continue
     43     cases.append(('lessons_'+name+'_'+name, True, expected))
     44 for name, io, expected in ([] if args.projects_only else cases):
     45     output, _ = s.run([s.tricu,'arboricx','run','--store',s.store,'--module',pin,
     46         '--name','demos_consumers_'+name+'.main','--format','decode',
     47         *(['--io','--unsafe-io'] if io else [])], 120)
     48     assert all(text in output for text in expected), (name,output)
     49     print(name + ': stored execution passed', flush=True)
     50 for name, expected in [('prefix-lines',b'matches=3\nfirst=disk\n'),
     51                        ('data-lines',b'data-lines=2\nfirst=alpha\n'),
     52                        ('fizzbuzz',b'ok: [1, 2, "Fizz"')]:
     53     prepared = s.root / (name+'.prepared')
     54     s.run([s.tricu,'scp','prepare',ROOT/f'demos/consumers/{name}/{name}.scp-project',
     55         '--bootstrap',bootstrap,'--store',s.store,'--output',prepared,'--seconds','600'],1100)
     56     if name == 'fizzbuzz':
     57         transport = ['--input-tree-file',ROOT/'demos/consumers/fizzbuzz/fizzbuzz-input.tree']
     58     else:
     59         transport = ['--input-file',ROOT / ('demos/consumers/data-lines/data-lines-input.txt' if name == 'data-lines' else 'demos/consumers/prefix-lines/tagged-log.fixture')]
     60     # Deployment runs must not depend on bootstrap artifacts or authored source.
     61     moved = s.root / 'bootstrap-hidden'; bootstrap.rename(moved)
     62     try:
     63         output, _ = s.run([s.tricu,'scp','run',prepared,*transport,'--seconds','60'],120)
     64     finally:
     65         moved.rename(bootstrap)
     66     assert expected in output,(name,output)
     67     print(name + ': native preparation and source-free deployment passed', flush=True)
     68 print('Focused SCP gate passed; not the historical broad matrix')
     69 
     70 # Failure controls: no legacy fallback, no accepting damaged executable graphs.
     71 missing = s.root / 'missing-bootstrap'; missing.mkdir(exist_ok=True)
     72 for selected, expected in [(missing,b'artifact bootstrap')]:
     73     try:
     74         s.run([s.tricu,'scp','build','--store',s.store,'--bootstrap',selected,'--seconds','10',
     75             '--workspace','demos.consumer-prefix-workspace','--directory',ROOT,'--compiler','0'*64],30)
     76     except AssertionError as error:
     77         assert expected in error.args[0][2],error
     78     else:
     79         raise AssertionError('missing bootstrap unexpectedly accepted')
     80 corrupt = bootstrap / 'scp-bootstrap.arboricx'
     81 original = corrupt.read_bytes(); altered = bytearray(original)
     82 # An arbitrary bit flip can create a *different valid program*, not malformed
     83 # input. This API has no external expected file digest. Corrupt the first graph
     84 # node tag deterministically; the container/header remain otherwise intact.
     85 import struct
     86 from stable_bundle import sections
     87 manifest_bytes, _ = sections(corrupt)
     88 altered[96 + len(manifest_bytes) + 8 + 4] = 255; corrupt.write_bytes(altered)
     89 try:
     90     try:
     91         s.run([s.tricu,'scp','build','--worker','--store',s.store,'--bootstrap',bootstrap,'--seconds','10',
     92             '--workspace','demos.consumer-prefix-workspace','--directory',ROOT,'--compiler','0'*64],30)
     93     except AssertionError as error:
     94         assert error.args[0][2],error
     95     else:
     96         raise AssertionError('corrupt bootstrap unexpectedly accepted')
     97 finally:
     98     corrupt.write_bytes(original)
     99 print('Missing/corrupt bootstrap controls passed')