aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/tools/ctest-driver.py
diff options
context:
space:
mode:
authorEgor Tensin <Egor.Tensin@gmail.com>2021-04-13 17:32:05 +0300
committerEgor Tensin <Egor.Tensin@gmail.com>2021-04-13 17:32:05 +0300
commit795dd9e87e44d1c49f160cd003cdde4113ee8247 (patch)
tree8235133e9007abdb53ed7380f201058c24269031 /tools/ctest-driver.py
parentREADME: fix badge links (diff)
downloadcmake-common-795dd9e87e44d1c49f160cd003cdde4113ee8247.tar.gz
cmake-common-795dd9e87e44d1c49f160cd003cdde4113ee8247.zip
tools: drop the .py extension
Diffstat (limited to 'tools/ctest-driver.py')
-rwxr-xr-xtools/ctest-driver.py166
1 files changed, 0 insertions, 166 deletions
diff --git a/tools/ctest-driver.py b/tools/ctest-driver.py
deleted file mode 100755
index 414e20c..0000000
--- a/tools/ctest-driver.py
+++ /dev/null
@@ -1,166 +0,0 @@
-#!/usr/bin/env python3
-
-# Copyright (c) 2021 Egor Tensin <Egor.Tensin@gmail.com>
-# This file is part of the "cmake-common" project.
-# For details, see https://github.com/egor-tensin/cmake-common.
-# Distributed under the MIT License.
-
-'''Wrap your actual test driver to use with CTest
-
-CTest suffers from at least two issues, in particular with regard to its
-PASS_REGULAR_EXPRESSION feature:
-
-1. The regular expression syntax used by CMake is deficient.
-2. The exit code of a test is ignored if one of the regexes matches.
-
-This script tries to fix them.
-'''
-
-import argparse
-import os
-import re
-import subprocess
-import sys
-
-
-SCRIPT_NAME = os.path.basename(__file__)
-
-
-def dump(msg, **kwargs):
- print(f'{SCRIPT_NAME}: {msg}', **kwargs)
-
-
-def err(msg):
- dump(msg, file=sys.stderr)
-
-
-def read_file(path):
- with open(path, mode='r') as fd:
- return fd.read()
-
-
-def run(cmd_line):
- try:
- result = subprocess.run(cmd_line, check=True, universal_newlines=True,
- stderr=subprocess.STDOUT,
- stdout=subprocess.PIPE)
- assert result.returncode == 0
- return result.stdout
- except subprocess.CalledProcessError as e:
- sys.stdout.write(e.output)
- sys.exit(e.returncode)
-
-
-def run_new_window(cmd_line):
- try:
- result = subprocess.run(cmd_line, check=True,
- creationflags=subprocess.CREATE_NEW_CONSOLE)
- assert result.returncode == 0
- return None
- except subprocess.CalledProcessError as e:
- sys.exit(e.returncode)
-
-
-def match(s, regex):
- return re.search(regex, s, flags=re.MULTILINE)
-
-
-def match_any(s, regexes):
- return any([match(s, regex) for regex in regexes])
-
-
-def match_all(s, regexes):
- return all([match(s, regex) for regex in regexes])
-
-
-def match_pass_regexes(output, regexes):
- if not regexes:
- return
- if not match_all(output, regexes):
- err("Couldn't match test program's output against all of the"\
- " regular expressions:")
- for regex in regexes:
- err(f'\t{regex}')
- sys.exit(1)
-
-
-def match_fail_regexes(output, regexes):
- if not regexes:
- return
- if match_any(output, regexes):
- err("Matched test program's output against some of the regular"\
- " expressions:")
- for regex in regexes:
- err(f'\t{regex}')
- sys.exit(1)
-
-
-def run_actual_test_driver(args):
- cmd_line = [args.exe_path] + args.exe_args
- run_func = run
- if args.new_window:
- run_func = run_new_window
- output = run_func(cmd_line)
- if args.new_window and (args.pass_regexes or args.fail_regexes):
- err("Cannot launch child process in a new window and capture its output")
- if output is not None:
- sys.stdout.write(output)
- match_pass_regexes(output, args.pass_regexes)
- match_fail_regexes(output, args.fail_regexes)
-
-
-def grep_file(args):
- contents = read_file(args.path)
- match_pass_regexes(contents, args.pass_regexes)
- match_fail_regexes(contents, args.fail_regexes)
-
-
-def parse_args(argv=None):
- if argv is None:
- argv = sys.argv[1:]
-
- parser = argparse.ArgumentParser(
- description=__doc__,
- formatter_class=argparse.RawDescriptionHelpFormatter)
-
- subparsers = parser.add_subparsers(dest='command')
-
- parser_run = subparsers.add_parser('run', help='run an executable and check its output')
- parser_run.add_argument('-p', '--pass-regex', nargs='*',
- dest='pass_regexes', metavar='REGEX',
- help='pass if all of these regexes match')
- parser_run.add_argument('-f', '--fail-regex', nargs='*',
- dest='fail_regexes', metavar='REGEX',
- help='fail if any of these regexes matches')
- parser_run.add_argument('-n', '--new-window', action='store_true',
- help='launch child process in a new console window')
- parser_run.add_argument('exe_path', metavar='PATH',
- help='path to the test executable')
- # nargs='*' here would discard additional '--'s.
- parser_run.add_argument('exe_args', metavar='ARG', nargs=argparse.REMAINDER,
- help='test executable arguments')
- parser_run.set_defaults(func=run_actual_test_driver)
-
- parser_grep = subparsers.add_parser('grep', help='check file contents for matching patterns')
- parser_grep.add_argument('-p', '--pass-regex', nargs='*',
- dest='pass_regexes', metavar='REGEX',
- help='pass if all of these regexes match')
- parser_grep.add_argument('-f', '--fail-regex', nargs='*',
- dest='fail_regexes', metavar='REGEX',
- help='fail if any of these regexes matches')
- parser_grep.add_argument('path', metavar='PATH', help='text file path')
- parser_grep.set_defaults(func=grep_file)
-
- args = parser.parse_args(argv)
- if args.command is None:
- parser.error('please specify a subcommand to run')
- return args
-
-
-def main(argv=None):
- args = parse_args(argv)
- args.func(args)
-
-
-if __name__ == '__main__':
- main()