#!/usr/bin/env python3 import argparse from pathlib import Path from typing import List, NamedTuple import shutil import subprocess import sys ROOT = Path(__file__).parent.parent.absolute() class TestOptions(NamedTuple): exe: Path toolchain: str def run_test_dir(dir: Path, opts: TestOptions) -> bool: print(f'Running test: {dir.stem} ', end='') out_dir = dir / '_build' if out_dir.exists(): shutil.rmtree(out_dir) res = subprocess.run( [ str(opts.exe), 'build', '--export', '--warnings', '--tests', f'--toolchain={opts.toolchain}', f'--out-dir={out_dir}', f'--export-name={dir.stem}', ], cwd=dir, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, ) if res.returncode != 0: print('- FAILED') print(f'Test failed with exit code ' f'[{res.returncode}]:\n{res.stdout.decode()}') else: print('- PASSED') return res.returncode == 0 def run_tests(opts: TestOptions) -> int: print('Sanity check...') subprocess.check_output([str(opts.exe), '--help']) tests_subdir = ROOT / 'tests' test_dirs = tests_subdir.glob('*.test') ret = 0 for td in test_dirs: if not run_test_dir(td, opts): ret = 1 return ret def bootstrap_self(opts: TestOptions): # Copy the exe to another location, as windows refuses to let a binary be # replaced while it is executing new_exe = ROOT / '_ddslime.bootstrap-test.exe' shutil.copy2(opts.exe, new_exe) res = subprocess.run([ str(new_exe), 'build', f'-FT{opts.toolchain}', ]) if res.returncode != 0: print('The bootstrap test failed!', file=sys.stderr) return False print('Bootstrap test PASSED!') return True def main(argv: List[str]) -> int: parser = argparse.ArgumentParser() parser.add_argument( '--exe', '-e', help='Path to the ddslim executable to test', required=True) parser.add_argument( '--toolchain', '-T', help='The ddslim toolchain to use while testing', required=True, ) parser.add_argument( '--skip-bootstrap-test', action='store_true', help='Skip the self-bootstrap test', ) args = parser.parse_args(argv) opts = TestOptions(exe=Path(args.exe).absolute(), toolchain=args.toolchain) if not args.skip_bootstrap_test and not bootstrap_self(opts): return 2 return run_tests(opts) if __name__ == "__main__": sys.exit(main(sys.argv[1:]))