1#!/usr/bin/env python3 2# SPDX-License-Identifier: LGPL-2.1-or-later 3 4import argparse 5import glob 6import os 7import pathlib 8import subprocess 9import sys 10try: 11 import colorama as c 12 GREEN = c.Fore.GREEN 13 YELLOW = c.Fore.YELLOW 14 RED = c.Fore.RED 15 RESET_ALL = c.Style.RESET_ALL 16 BRIGHT = c.Style.BRIGHT 17except ImportError: 18 GREEN = YELLOW = RED = RESET_ALL = BRIGHT = '' 19 20class total: 21 total = None 22 good = 0 23 skip = 0 24 fail = 0 25 26def argument_parser(): 27 p = argparse.ArgumentParser() 28 p.add_argument('-u', '--unsafe', action='store_true', 29 help='run "unsafe" tests too') 30 p.add_argument('-A', '--artifact_directory', 31 help='store output from failed tests in this dir') 32 return p 33 34opts = argument_parser().parse_args() 35 36tests = glob.glob('/usr/lib/systemd/tests/test-*') 37if opts.unsafe: 38 tests += glob.glob('/usr/lib/systemd/tests/unsafe/test-*') 39 40if not opts.artifact_directory and os.getenv('ARTIFACT_DIRECTORY'): 41 opts.artifact_directory = os.getenv('ARTIFACT_DIRECTORY') 42 43total.total = len(tests) 44for test in tests: 45 name = os.path.basename(test) 46 47 ex = subprocess.run(test, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 48 if ex.returncode == 0: 49 print(f'{GREEN}PASS: {name}{RESET_ALL}') 50 total.good += 1 51 elif ex.returncode == 77: 52 print(f'{YELLOW}SKIP: {name}{RESET_ALL}') 53 total.skip += 1 54 else: 55 print(f'{RED}FAIL: {name}{RESET_ALL}') 56 total.fail += 1 57 58 output_file = None 59 if opts.artifact_directory: 60 output_dir = pathlib.Path(opts.artifact_directory) / 'unit-tests' 61 output_dir.mkdir(parents=True, exist_ok=True) 62 output_file = output_dir / name 63 output_file.write_bytes(ex.stdout) 64 65 try: 66 print(ex.stdout.decode('utf-8')) 67 except UnicodeDecodeError: 68 print(f'{BRIGHT}Note, some test output shown here is not UTF-8') 69 if output_file: 70 print(f'For actual test output see artifact file {output_file}') 71 print(f'{RESET_ALL}') 72 print(ex.stdout.decode('utf-8', errors='replace')) 73 sys.stdout.flush() 74 75 76print(f'{BRIGHT}OK: {total.good} SKIP: {total.skip} FAIL: {total.fail}{RESET_ALL}') 77sys.exit(total.fail > 0) 78