mirror of
https://gitlab.gnome.org/GNOME/libsecret.git
synced 2024-12-22 20:58:52 +00:00
b72048c920
Allow parallel building and testing by using a single Makefile.am Implement parallel testing using TAP, with various drivers and compilers living in the build/ directory. Fix all sorts of issues that this caused, including builddir != srcdir, leaks in tests and so on. It would have been nice to break out all the above into separate commits ... blush.
175 lines
5.9 KiB
Python
Executable File
175 lines
5.9 KiB
Python
Executable File
#!/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":
|
|
print "ok %d # skip -- %s" % (self.test_num, self.test_name)
|
|
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:
|
|
raise subprocess.CalledProcessError(proc.returncode, self.command)
|
|
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 ]:
|
|
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))
|