|
- #!/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:
- fails = 0
- fails += _run_subproc_test(
- dir,
- opts,
- 'Full Build',
- 'build',
- '--full',
- f'--toolchain={opts.toolchain}',
- )
- fails += _run_subproc_test(
- dir,
- opts,
- 'Source Distribution',
- 'sdist',
- 'create',
- f'--out=_build/{dir.stem}/test.dsd',
- '--replace',
- )
- return fails == 0
-
-
- def _run_subproc_test(dir: Path, opts: TestOptions, name: str,
- *args: str) -> int:
- print(f'Running test: {dir.stem} - {name} ', end='')
- out_dir = dir / '_build'
- if out_dir.exists():
- shutil.rmtree(out_dir)
- res = subprocess.run(
- [
- str(opts.exe),
- ] + list(str(s) for s in args),
- 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()}')
- return 1
- print('- PASSED')
- return 0
-
-
- def _run_build_test(dir: Path, opts: TestOptions) -> int:
- print(f'Running test: {dir.stem} - build', end='')
- out_dir = dir / '_build'
- if out_dir.exists():
- shutil.rmtree(out_dir)
- res = subprocess.run(
- [
- str(opts.exe),
- 'build',
- '--export',
- '--warnings',
- '--tests',
- '--full',
- f'--toolchain={opts.toolchain}',
- f'--out={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()}')
- return 1
- print('- PASSED')
- return 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 / '_dds.bootstrap-test.exe'
- shutil.copy2(opts.exe, new_exe)
- res = subprocess.run([
- str(new_exe),
- 'build',
- f'-FT{opts.toolchain}',
- ])
- new_exe.unlink()
- 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 dds executable to test',
- required=True)
- parser.add_argument(
- '--toolchain',
- '-T',
- help='The dds 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)
-
- tc = args.toolchain
- if not tc.startswith(':'):
- tc = Path(tc).absolute()
- opts = TestOptions(exe=Path(args.exe).absolute(), toolchain=tc)
-
- 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:]))
|