162306a36Sopenharmony_ci#!/usr/bin/env python3
262306a36Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0
362306a36Sopenharmony_ci#
462306a36Sopenharmony_ci# This file runs some basic checks to verify kunit works.
562306a36Sopenharmony_ci# It is only of interest if you're making changes to KUnit itself.
662306a36Sopenharmony_ci#
762306a36Sopenharmony_ci# Copyright (C) 2021, Google LLC.
862306a36Sopenharmony_ci# Author: Daniel Latypov <dlatypov@google.com.com>
962306a36Sopenharmony_ci
1062306a36Sopenharmony_cifrom concurrent import futures
1162306a36Sopenharmony_ciimport datetime
1262306a36Sopenharmony_ciimport os
1362306a36Sopenharmony_ciimport shutil
1462306a36Sopenharmony_ciimport subprocess
1562306a36Sopenharmony_ciimport sys
1662306a36Sopenharmony_ciimport textwrap
1762306a36Sopenharmony_cifrom typing import Dict, List, Sequence
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ciABS_TOOL_PATH = os.path.abspath(os.path.dirname(__file__))
2062306a36Sopenharmony_ciTIMEOUT = datetime.timedelta(minutes=5).total_seconds()
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_cicommands: Dict[str, Sequence[str]] = {
2362306a36Sopenharmony_ci	'kunit_tool_test.py': ['./kunit_tool_test.py'],
2462306a36Sopenharmony_ci	'kunit smoke test': ['./kunit.py', 'run', '--kunitconfig=lib/kunit', '--build_dir=kunit_run_checks'],
2562306a36Sopenharmony_ci	'pytype': ['/bin/sh', '-c', 'pytype *.py'],
2662306a36Sopenharmony_ci	'mypy': ['mypy', '--config-file', 'mypy.ini', '--exclude', '_test.py$', '--exclude', 'qemu_configs/', '.'],
2762306a36Sopenharmony_ci}
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci# The user might not have mypy or pytype installed, skip them if so.
3062306a36Sopenharmony_ci# Note: you can install both via `$ pip install mypy pytype`
3162306a36Sopenharmony_cinecessary_deps : Dict[str, str] = {
3262306a36Sopenharmony_ci	'pytype': 'pytype',
3362306a36Sopenharmony_ci	'mypy': 'mypy',
3462306a36Sopenharmony_ci}
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_cidef main(argv: Sequence[str]) -> None:
3762306a36Sopenharmony_ci	if argv:
3862306a36Sopenharmony_ci		raise RuntimeError('This script takes no arguments')
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci	future_to_name: Dict[futures.Future[None], str] = {}
4162306a36Sopenharmony_ci	executor = futures.ThreadPoolExecutor(max_workers=len(commands))
4262306a36Sopenharmony_ci	for name, argv in commands.items():
4362306a36Sopenharmony_ci		if name in necessary_deps and shutil.which(necessary_deps[name]) is None:
4462306a36Sopenharmony_ci			print(f'{name}: SKIPPED, {necessary_deps[name]} not in $PATH')
4562306a36Sopenharmony_ci			continue
4662306a36Sopenharmony_ci		f = executor.submit(run_cmd, argv)
4762306a36Sopenharmony_ci		future_to_name[f] = name
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	has_failures = False
5062306a36Sopenharmony_ci	print(f'Waiting on {len(future_to_name)} checks ({", ".join(future_to_name.values())})...')
5162306a36Sopenharmony_ci	for f in  futures.as_completed(future_to_name.keys()):
5262306a36Sopenharmony_ci		name = future_to_name[f]
5362306a36Sopenharmony_ci		ex = f.exception()
5462306a36Sopenharmony_ci		if not ex:
5562306a36Sopenharmony_ci			print(f'{name}: PASSED')
5662306a36Sopenharmony_ci			continue
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci		has_failures = True
5962306a36Sopenharmony_ci		if isinstance(ex, subprocess.TimeoutExpired):
6062306a36Sopenharmony_ci			print(f'{name}: TIMED OUT')
6162306a36Sopenharmony_ci		elif isinstance(ex, subprocess.CalledProcessError):
6262306a36Sopenharmony_ci			print(f'{name}: FAILED')
6362306a36Sopenharmony_ci		else:
6462306a36Sopenharmony_ci			print(f'{name}: unexpected exception: {ex}')
6562306a36Sopenharmony_ci			continue
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci		output = ex.output
6862306a36Sopenharmony_ci		if output:
6962306a36Sopenharmony_ci			print(textwrap.indent(output.decode(), '> '))
7062306a36Sopenharmony_ci	executor.shutdown()
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci	if has_failures:
7362306a36Sopenharmony_ci		sys.exit(1)
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_cidef run_cmd(argv: Sequence[str]) -> None:
7762306a36Sopenharmony_ci	subprocess.check_output(argv, stderr=subprocess.STDOUT, cwd=ABS_TOOL_PATH, timeout=TIMEOUT)
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ciif __name__ == '__main__':
8162306a36Sopenharmony_ci	main(sys.argv[1:])
82