tricu

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

bootstrap_retention_probe.py (5682B)


      1 #!/usr/bin/env python3
      2 """Isolated retained-toolchain probes, invoked only by bootstrap_retention.py.
      3 No compiler generation checkpoint or fixture publication is created here.
      4 """
      5 import argparse
      6 import hashlib
      7 import json
      8 from pathlib import Path
      9 import subprocess
     10 import sys
     11 
     12 from bootstrap_retention import REPO, sha, save
     13 from bootstrap_acceptance import verify
     14 
     15 
     16 def main():
     17     p = argparse.ArgumentParser(description=__doc__)
     18     p.add_argument('--root', type=Path, required=True)
     19     p.add_argument('--plan', type=Path, required=True)
     20     p.add_argument('--directory', type=Path, required=True)
     21     a = p.parse_args()
     22     plan = json.loads(a.plan.read_text()); config = plan['config']
     23     root, out = a.root, a.directory
     24     # Refuse a non-isolated invocation; every removal target must be invisible.
     25     if any((root / row['objects']).exists() for row in plan['stores']):
     26         raise ValueError('obsolete object stores are still visible')
     27     report = dict(complete=False, obsolete_stores_hidden=True, toolchains=[])
     28     def run(label, command, seconds=900):
     29         with (out / (label + '.log')).open('w') as log:
     30             subprocess.run(command, stdout=log, stderr=subprocess.STDOUT, check=True, timeout=seconds)
     31     try:
     32         for t in config['toolchains']:
     33             role = t['role']; generation = root / t['generation']; source = root / t['source']
     34             acceptance = root / t['acceptance']; runtime = t['runtime']
     35             accepted = json.loads(acceptance.read_text())
     36             # These cohorts still include first generation, so rerun full-pair
     37             # acceptance as well as the generation-two audit. Portable-only
     38             # retirement of first generation needs an explicitly different gate.
     39             fresh = verify(Path(accepted['generations'][0]), generation, Path(runtime), source)
     40             if fresh['artifacts'] != accepted['artifacts']:
     41                 raise ValueError('retained acceptance artifacts differ')
     42             run(role + '-portable', [sys.executable, str(REPO / 'test/portable_cli.py'), runtime,
     43                 '--backend', 'stable', '--indexed', '--compiler-bundle', str(generation / 'build-stable.arboricx')])
     44             run(role + '-smoke', [sys.executable, str(REPO / 'test/bootstrap_smoke.py'), runtime,
     45                 '--generation', str(generation), '--acceptance', str(acceptance),
     46                 '--source-root', str(source), '--directory', str(out / (role + '-smoke'))])
     47             scoped = out / (role + '-map')
     48             run(role + '-map', [sys.executable, str(REPO / 'test/bootstrap_generations.py'),
     49                 str(generation), str(scoped), '--tricu', runtime, '--source-root', str(source),
     50                 '--map', str(generation / 'source-map.v1'), '--root', 'native_math', '--backend', 'stable',
     51                 '--fresh', '--adapter', str(generation / 'io-adapter.arboricx'), '--capabilities', '2',
     52                 '--memory-mib', '8192', '--wall-seconds', '900'])
     53             run(role + '-map-audit', [sys.executable, str(REPO / 'test/bootstrap_store_check.py'),
     54                 str(scoped), '--source-root', str(source), '--root', 'native_math'])
     55             old = (generation / 'cas/cache/source-build/native_math').read_text().split('\t')[2]
     56             new = (scoped / 'cas/cache/source-build/native_math').read_text().split('\t')[2]
     57             if old != new:
     58                 raise ValueError('scoped map-builder changed complete native_math manifest')
     59             smoke = json.loads((out / (role + '-smoke/report.json')).read_text())
     60             if not smoke['complete'] or not smoke['wrong_output_rejected']:
     61                 raise ValueError('incomplete retained compiler smoke')
     62             report['toolchains'].append(dict(role=role, artifacts=fresh['artifacts'],
     63                 acceptance_sha256=sha(acceptance), runtime_sha256=sha(runtime),
     64                 fresh_pair_audits=fresh['audits'], portable_cli=True,
     65                 complete_results=len(smoke['cases']), scoped_map_manifest=new))
     66         support = config['support']
     67         runtime = next(t['runtime'] for t in config['toolchains'] if t['role'] == support['toolchain'])
     68         publication = out / 'support-reproduced'
     69         command = [sys.executable, str(REPO / 'test/repair_support_fixture.py'), runtime,
     70             str(root / support['preparation']), '--output-directory', str(publication),
     71             '--capabilities', '2', '--verification-memory-mib', '8192']
     72         if support.get('relocate_patterns'):
     73             command += ['--relocate-patterns']
     74         run('support', command, seconds=1500)
     75         compared = {}
     76         for name in ['support-library.arboricx', 'support-rebuilt.arboricx', 'support-library.v1']:
     77             if sha(publication / name) != sha(REPO / 'test/fixtures' / name):
     78                 raise ValueError('current support fixture did not reproduce: ' + name)
     79             compared[name] = sha(publication / name)
     80         expected = REPO / 'test/fixtures/support-receipts'
     81         actual = publication / 'support-receipts'
     82         if {p.name: sha(p) for p in actual.iterdir()} != {p.name: sha(p) for p in expected.iterdir()}:
     83             raise ValueError('support receipt/manifests did not reproduce')
     84         run('fixture-freshness', [sys.executable, str(REPO / 'test/fixture_sources.py'), 'current'])
     85         report.update(complete=True, support_sha256=compared,
     86                       support_receipts_reproduced=True, fixture_sources_current=True)
     87     finally:
     88         save(out / 'report.json', report)
     89     print('PASS isolated pair audits, CLI integrity/diagnostics, correctness smokes, scoped map-builds and support reproduction')
     90 
     91 
     92 if __name__ == '__main__':
     93     main()