tricu

A lazy functional language based on Tree Calculus
Log | Files | Refs | README | LICENSE

shared_library_smoke.py (4525B)


      1 #!/usr/bin/env python3
      2 """Compile and audit one application, then compare CLI/C-ABI complete results.
      3 
      4 The independent imports/recursive-list/invoice oracles also serve compiler
      5 post-acceptance smokes. This uses the packaged compiler and creates no compiler
      6 generation or acceptance checkpoint.
      7 """
      8 import argparse
      9 import json
     10 import os
     11 from pathlib import Path
     12 import re
     13 import sys
     14 from bootstrap_smoke import LIBRARY, PROGRAM, smoke_cases, sha
     15 from collections_batch import ProbeRunner, audit_workspace
     16 from native_library_migration import digest
     17 from process_rss import run_guarded
     18 
     19 ROOT = Path(__file__).resolve().parent.parent
     20 
     21 
     22 def main():
     23     parser = argparse.ArgumentParser(description=__doc__)
     24     parser.add_argument('--tricu', type=Path, required=True)
     25     parser.add_argument('--library', type=Path, required=True)
     26     parser.add_argument('--directory', type=Path, required=True)
     27     args = parser.parse_args()
     28     root = args.directory.resolve()
     29     root.mkdir(parents=True, exist_ok=False)
     30     workspace = root / 'workspace'
     31     workspace.mkdir()
     32     (workspace / 'tricu.workspace').write_text('tricu.workspace.v1\n')
     33     for alias, relative in {'base':'lib/base.tri', 'bytes':'lib/bytes.tri',
     34                             'conversions':'lib/conversions.tri', 'prelude':'lib/prelude.tri',
     35                             'native_math':'lib/math/native.tri',
     36                             'shapes':'demos/source-patterns/patterns.tri'}.items():
     37         (workspace / (alias + '.tri')).write_bytes((ROOT / relative).read_bytes())
     38     (workspace / 'recursive.tri').write_text(LIBRARY)
     39     (workspace / 'program.tri').write_text(PROGRAM)
     40     # Per-process test allocator policy; no library initialization changes.
     41     os.environ['MALLOC_ARENA_MAX'] = '2'
     42     runner = ProbeRunner(args.tricu, root, 300)
     43     report = dict(complete=False, compiler_sha256=sha(ROOT / 'bootstrap/build-stable.arboricx'),
     44                   runtime_sha256=sha(args.library), observer_sha256=sha(ROOT / 'test/haskell_observe.py'),
     45                   binding_sha256=sha(ROOT / 'ext/haskell/python/tricu.py'), cases=[],
     46                   scope='packaged compiler application; no compiler generation')
     47     try:
     48         tool = runner.imported(ROOT / 'bootstrap/build-stable.arboricx', 'compiler')
     49         bundle = root / 'program.arboricx'
     50         runner.run('compile', ['compile', '--file', workspace/'program.tri',
     51                    '--toolchain', tool, '--toolchain-io-version', '2', '--tool-store', runner.store,
     52                    '--store', runner.store, '--output', bundle, '--compile-timeout', '180'], 210)
     53         manifest_bytes = (runner.store / 'objects' / tool[:3] / tool).read_bytes()
     54         assert digest('arboricx.module-manifest.v1', manifest_bytes) == tool
     55         compiler = next(row.split('\t')[3] for row in manifest_bytes.decode().splitlines()[1:]
     56                         if row.split('\t')[1] == 'sourceBuildGraph')
     57         report['modules'] = audit_workspace(workspace, runner.store, compiler)
     58         imported = runner.run('import-program', ['import', '--file', bundle, '--store', runner.store])
     59         manifest = re.search(r'Created module alias .* -> ([0-9a-f]{64})', imported)[1]
     60         assert manifest == report['modules']['program']['manifest']
     61         for i, (export, argument, expected) in enumerate(smoke_cases()):
     62             path, output = root / f'{i}.input.tree', root / f'{i}.output.tree'
     63             path.write_bytes(argument)
     64             actual = runner.invoke(str(i), manifest, export, ['--arg-tree-file', path])
     65             assert actual == expected, (export, i, 'CLI')
     66             reply, peak = run_guarded([sys.executable, str(ROOT / 'test/haskell_observe.py'),
     67                 '--library', str(args.library), '--bundle', str(bundle), '--export', export,
     68                 '--argument', str(path), '--output', str(output)], memory_mib=512, seconds=65)
     69             (root / f'{i}.log').write_text(reply)
     70             assert output.read_bytes() == expected, (export, i, 'C ABI')
     71             report['cases'].append(dict(export=export, input_sha256=sha(path),
     72                                         output_sha256=sha(output), peak_kib=peak))
     73         assert output.read_bytes() != b'\0', 'wrong-output control'
     74         report.update(complete=True, bundle_sha256=sha(bundle), wrong_output_rejected=True)
     75         print('PASS: 12 independent complete results through CLI and C ABI')
     76     finally:
     77         (root / 'report.json').write_text(json.dumps(report, indent=2) + '\n')
     78 
     79 
     80 if __name__ == '__main__':
     81     main()