diff options
author | Stef Walter <stefw@gnome.org> | 2014-03-05 12:25:24 +0100 |
---|---|---|
committer | Stef Walter <stefw@gnome.org> | 2014-03-05 13:01:15 +0100 |
commit | 7555cdcab98022e7336e4e49309b6b7d3359b636 (patch) | |
tree | fd20019a5accb8135c6da4be9db6e7bd4712d013 /build/tap-gtester | |
parent | ae6526d2b6e4e1fd613482929a1b4ea0c117d69f (diff) |
Makefile.am: Implement proper make check-memory target
Uses valgrind to run the tests. Update the tap-driver and
tap-gtester pieces to accomodate this.
Diffstat (limited to 'build/tap-gtester')
-rwxr-xr-x | build/tap-gtester | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/build/tap-gtester b/build/tap-gtester new file mode 100755 index 0000000..ff7506a --- /dev/null +++ b/build/tap-gtester @@ -0,0 +1,176 @@ +#!/usr/bin/python + +# Copyright (C) 2014 Red Hat, Inc. +# +# Cockpit is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# Cockpit is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Cockpit; If not, see <http://www.gnu.org/licenses/>. + +# +# This is a test output compiler which produces TAP from GTest output +# if GTest output is detected. +# +# Versions of glib later than 2.38.x output TAP natively when tests are +# run with the --tap option. However we can't depend on such a recent +# version of glib for our purposes. +# +# This implements the Test Anything Protocol (ie: TAP) +# https://metacpan.org/pod/release/PETDANCE/Test-Harness-2.64/lib/Test/Harness/TAP.pod +# + +import argparse +import os +import select +import subprocess +import sys + +class NullCompiler: + def __init__(self, command): + self.command = command + + def input(self, line): + sys.stdout.write(line) + + def process(self, proc): + while True: + line = proc.stdout.readline() + if not line: + break + self.input(line) + proc.wait() + return proc.returncode + + def run(self, proc, line=None): + if line: + self.input(line) + return self.process(proc) + + +class GTestCompiler(NullCompiler): + def __init__(self, filename): + NullCompiler.__init__(self, filename) + self.test_num = 0 + self.test_name = None + self.test_remaining = [] + + def input(self, line): + line = line.strip() + if line.startswith("GTest: "): + (cmd, unused, data) = line[7:].partition(": ") + cmd = cmd.strip() + data = data.strip() + if cmd == "run": + self.test_name = data + assert self.test_name in self.test_remaining, "%s %s" % (self.test_name, repr(self.test_remaining)) + self.test_remaining.remove(self.test_name) + self.test_num += 1 + elif cmd == "result": + if data == "OK": + print "ok %d %s" % (self.test_num, self.test_name) + if data == "FAIL": + print "not ok %d %s", (self.test_num, self.test_name) + self.test_name = None + elif cmd == "skipping": + if "/subprocess" not in data: + print "ok %d # skip -- %s" % (self.test_num, data) + self.test_name = None + elif data: + print "# %s: %s" % (cmd, data) + else: + print "# %s" % cmd + elif line.startswith("(MSG: "): + print "# %s" % line[6:-1] + elif line: + print "# %s" % line + sys.stdout.flush() + + def run(self, proc, output=""): + # Complete retrieval of the list of tests + output += proc.stdout.read() + proc.wait() + if proc.returncode: + sys.stderr.write("tap-gtester: listing GTest tests failed: %d\n" % proc.returncode) + return proc.returncode + self.test_remaining = [] + for line in output.split("\n"): + if line.startswith("/"): + self.test_remaining.append(line.strip()) + if not self.test_remaining: + print "Bail out! No tests found in GTest: %s" % self.command[0] + return 0 + + print "1..%d" % len(self.test_remaining) + + # First try to run all the tests in a batch + proc = subprocess.Popen(self.command + ["--verbose" ], close_fds=True, stdout=subprocess.PIPE) + result = self.process(proc) + if result == 0: + return 0 + + # Now pick up any stragglers due to failures + while True: + # Assume that the last test failed + if self.test_name: + print "not ok %d %s" % (self.test_num, self.test_name) + self.test_name = None + + # Run any tests which didn't get run + if not self.test_remaining: + break + + proc = subprocess.Popen(self.command + ["--verbose", "-p", self.test_remaining[0]], + close_fds=True, stdout=subprocess.PIPE) + result = self.process(proc) + + # The various exit codes and signals we continue for + if result not in [ 0, 1, -4, -5, -6, -7, -8, -11, 33 ]: + break + + return result + +def main(argv): + parser = argparse.ArgumentParser(description='Automake TAP compiler') + parser.add_argument('--format', metavar='FORMAT', choices=[ "auto", "gtest", "tap" ], + default="auto", help='The input format to compile') + parser.add_argument('--verbose', action='store_true', + default=True, help='Verbose mode (ignored)') + parser.add_argument('command', nargs='+', help="A test command to run") + args = parser.parse_args(argv[1:]) + + output = None + format = args.format + cmd = args.command + proc = None + + if format in ["auto", "gtest"]: + list_cmd = cmd + ["-l", "--verbose"] + proc = subprocess.Popen(list_cmd, close_fds=True, stdout=subprocess.PIPE) + output = proc.stdout.readline() + # Smell whether we're dealing with GTest list output from first line + if "random seed" in output or "GTest" in output or output.startswith("/"): + format = "gtest" + else: + format = "tap" + else: + proc = subprocess.Popen(cmd, close_fds=True, stdout=subprocess.PIPE) + + if format == "gtest": + compiler = GTestCompiler(cmd) + elif format == "tap": + compiler = NullCompiler(cmd) + else: + assert False, "not reached" + + return compiler.run(proc, output) + +if __name__ == "__main__": + sys.exit(main(sys.argv)) |