[gcr] Makefile.am: Implement proper make check-memory target
- From: Stefan Walter <stefw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gcr] Makefile.am: Implement proper make check-memory target
- Date: Wed, 5 Mar 2014 12:03:54 +0000 (UTC)
commit 7555cdcab98022e7336e4e49309b6b7d3359b636
Author: Stef Walter <stefw gnome org>
Date: Wed Mar 5 12:25:24 2014 +0100
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.
.gitignore | 1 +
Makefile.am | 54 +++++++--
build/Makefile.am | 34 ------
build/tap-driver | 215 +++++++++++++++++++++++------------
build/{tap-compiler => tap-gtester} | 20 ++--
5 files changed, 197 insertions(+), 127 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index ea2e9c4..ff41d82 100644
--- a/.gitignore
+++ b/.gitignore
@@ -114,3 +114,4 @@ stamp-*
/build/coverage
/build/coverage.info
/build/valgrind-suppressions
+/build/test-driver
diff --git a/Makefile.am b/Makefile.am
index 37bbdd5..af36e6a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -8,12 +8,6 @@ SUBDIRS = \
ACLOCAL_AMFLAGS = -I build/m4 ${ACLOCAL_FLAGS}
-EXTRA_DIST = \
- intltool-extract.in \
- intltool-merge.in \
- intltool-update.in \
- HACKING
-
DISTCHECK_CONFIGURE_FLAGS = \
--enable-gtk-doc \
--enable-strict \
@@ -42,15 +36,40 @@ dist-hook:
echo A git clone is required to generate a ChangeLog >&2; \
fi
-check-memory:
- make -C gcr check-memory
-
check-local: check-gck-symbols check-gcr-symbols check-ui-symbols
upload-release: $(DIST_ARCHIVES)
scp $(DIST_ARCHIVES) master.gnome.org:
ssh master.gnome.org ftpadmin install $(DIST_ARCHIVES)
+# Default executable tests
+LOG_DRIVER = $(srcdir)/build/tap-driver
+LOG_DRIVER_FLAGS = --format=tap
+LOG_COMPILER = $(srcdir)/build/tap-gtester
+
+VALGRIND_ARGS = --trace-children=no --quiet --error-exitcode=33 \
+ --suppressions=valgrind-suppressions --gen-suppressions=all \
+ --num-callers=16
+VALGRIND_SUPPRESSIONS = \
+ build/gcr.supp \
+ build/gcrypt.supp \
+ build/glib.supp \
+ build/glibc.supp \
+ build/p11-kit.supp \
+ build/pixman.supp \
+ build/pthread.supp \
+ build/unknown.supp
+
+valgrind-suppressions: $(VALGRIND_SUPPRESSIONS)
+ $(AM_V_GEN) cat $^ > $@
+
+check-memory: valgrind-suppressions
+ $(MAKE) LOG_FLAGS="-- libtool --mode=execute valgrind $(VALGRIND_ARGS)" \
+ $(AM_MAKEFLAGS) check
+recheck-memory: valgrind-suppressions
+ $(MAKE) LOG_FLAGS="-- libtool --mode=execute valgrind $(VALGRIND_ARGS)" \
+ $(AM_MAKEFLAGS) recheck
+
AM_CPPFLAGS = \
-I$(srcdir) \
-I$(builddir) \
@@ -63,9 +82,6 @@ AM_CPPFLAGS = \
LDADD = \
$(GLIB_LIBS)
-LOG_DRIVER = $(srcdir)/build/tap-driver
-LOG_COMPILER = $(srcdir)/build/tap-compiler
-
BUILT_SOURCES =
TESTS =
@@ -81,6 +97,19 @@ pkgconfigdir = $(libdir)/pkgconfig
CLEANFILES = \
$(pkgconfig_DATA)
+EXTRA_DIST = \
+ intltool-extract.in \
+ intltool-merge.in \
+ intltool-update.in \
+ HACKING \
+ build/valgrind \
+ $(VALGRIND_SUPPRESSIONS) \
+ build/enum-template.c \
+ build/enum-template.h \
+ build/g-ir-unbreak.xsl \
+ build/tap-driver \
+ build/tap-gtester
+
TEST_SUPPRESSIONS = $(top_builddir)/build/valgrind-suppressions
V_SED = $(V_SED_$(V))
@@ -162,7 +191,6 @@ endif
endif
-include build/Makefile.am
include egg/Makefile.am
include gck/Makefile.am
include gcr/Makefile.am
diff --git a/build/tap-driver b/build/tap-driver
index eb22462..3906b40 100755
--- a/build/tap-driver
+++ b/build/tap-driver
@@ -35,21 +35,16 @@ import subprocess
import sys
class Driver:
- def __init__(self, command, args):
- self.argv = command
- self.output = ""
+ def __init__(self, args):
+ self.argv = args.command
self.test_name = args.test_name
self.log = open(args.log_file, "w")
+ self.log.write("# %s\n" % " ".join(sys.argv))
self.trs = open(args.trs_file, "w")
self.color_tests = args.color_tests
self.expect_failure = args.expect_failure
- self.reported = { }
- self.test_plan = None
- self.late_plan = False
- self.errored = False
- self.bail_out = False
- def report(self, code, num, *args):
+ def report(self, code, *args):
CODES = {
"XPASS": '\x1b[0;31m', # red
"FAIL": '\x1b[0;31m', # red
@@ -69,9 +64,6 @@ class Driver:
sys.stdout.write(": ")
sys.stdout.write(self.test_name)
sys.stdout.write(" ")
- if num:
- sys.stdout.write(str(num))
- sys.stdout.write(" ")
for arg in args:
sys.stdout.write(str(arg))
sys.stdout.write("\n")
@@ -79,32 +71,81 @@ class Driver:
# Book keeping
if code in CODES:
- if num != None:
- self.reported[num] = code
self.trs.write(":test-result: %s\n" % code)
- if code == "ERROR":
- self.errored = True
- def result_pass(self, num, description):
+ def result_pass(self, *args):
if self.expect_failure:
- self.report("XPASS", num, description)
+ self.report("XPASS", *args)
else:
- self.report("PASS", num, description)
+ self.report("PASS", *args)
- def result_fail(self, num, description):
+ def result_fail(self, *args):
if self.expect_failure:
- self.report("XFAIL", num, description)
+ self.report("XFAIL", *args)
else:
- self.report("FAIL", num, description)
+ self.report("FAIL", *args)
- def result_skip(self, num, description, ok):
+ def result_skip(self, *args):
if self.expect_failure:
- self.report("XFAIL", num, description)
+ self.report("XFAIL", *args)
else:
- self.report("SKIP", num, description)
+ self.report("SKIP", *args)
- def report_error(self, problem):
- self.report("ERROR", None, problem)
+ def report_error(self, description=""):
+ self.report("ERROR", "", description)
+
+ def process(self, output):
+ pass
+
+ def execute(self):
+ try:
+ proc = subprocess.Popen(self.argv, close_fds=True,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ except OSError, ex:
+ self.report_error("Couldn't run %s: %s" % (self.argv[0], str(ex)))
+ return
+
+ outf = proc.stdout.fileno()
+ errf = proc.stderr.fileno()
+ rset = [outf, errf]
+ while len(rset) > 0:
+ ret = select.select(rset, [], [], 10)
+ if outf in ret[0]:
+ data = os.read(outf, 1024)
+ if data == "":
+ rset.remove(outf)
+ self.log.write(data)
+ self.process(data)
+ if errf in ret[0]:
+ data = os.read(errf, 1024)
+ if data == "":
+ rset.remove(errf)
+ self.log.write(data)
+ sys.stderr.write(data)
+
+ proc.wait()
+ return proc.returncode
+
+
+class TapDriver(Driver):
+ def __init__(self, args):
+ Driver.__init__(self, args)
+ self.output = ""
+ self.reported = { }
+ self.test_plan = None
+ self.late_plan = False
+ self.errored = False
+ self.bail_out = False
+
+ def report(self, code, num, *args):
+ if num:
+ Driver.report(self, code, num, " ", *args)
+ self.reported[num] = code
+ else:
+ Driver.report(self, code, *args)
+ if code == "ERROR":
+ self.errored = True
def consume_test_line(self, ok, data):
# It's an error if the caller sends a test plan in the middle of tests
@@ -117,13 +158,13 @@ class Driver:
try:
num = int(num)
except ValueError:
- self.report_error("Invalid test number: %s" % data)
+ self.report_error("Invalid test number: %s" % data)
return
description = description.lstrip()
# Special case if description starts with this, then skip
if description.lower().startswith("# skip"):
- self.result_skip(num, description, ok)
+ self.result_skip(num, description)
elif ok:
self.result_pass(num, description)
else:
@@ -149,12 +190,13 @@ class Driver:
self.bail_out = True
self.report("SKIP", 0, line)
- def drain(self):
+ def process(self, output):
+ if output:
+ self.output += output
+ elif self.output:
+ self.output += "\n"
(ready, unused, self.output) = self.output.rpartition("\n")
for line in ready.split("\n"):
- self.log.write(line)
- self.log.write("\n")
-
if line.startswith("ok "):
self.consume_test_line(True, line[3:])
elif line.startswith("not ok "):
@@ -165,41 +207,8 @@ class Driver:
elif line.lower().startswith("bail out!"):
self.consume_bail_out(line)
- def execute(self):
- try:
- proc = subprocess.Popen(self.argv, close_fds=True,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- except OSError, ex:
- self.report_error("Couldn't run %s: %s" % (self.argv[0], str(ex)))
- return
-
- outf = proc.stdout.fileno()
- errf = proc.stderr.fileno()
- rset = [outf, errf]
- while len(rset) > 0:
- ret = select.select(rset, [], [], 10)
- if outf in ret[0]:
- data = os.read(outf, 1024)
- if data == "":
- if self.output:
- self.output += "\n"
- rset.remove(outf)
- else:
- self.output += data
- self.drain()
- if errf in ret[0]:
- data = os.read(errf, 1024)
- if data == "":
- rset.remove(errf)
- self.log.write(data)
- sys.stderr.write(data)
-
- proc.wait()
- self.returncode = proc.returncode
-
def run(self):
- self.execute()
+ returncode = self.execute()
failed = False
skipped = True
@@ -213,6 +222,10 @@ class Driver:
if code != "SKIP":
skipped = False
+ if not self.errored and returncode:
+ self.report_error("process failed: %d" % returncode)
+ self.errored = True
+
# Check the plan
if not self.errored:
if not self.test_plan:
@@ -231,7 +244,7 @@ class Driver:
if self.errored:
self.trs.write(":global-test-result: ERROR\n")
self.trs.write(":test-global-result: ERROR\n")
- self.trs.write(":recheck: no\n")
+ self.trs.write(":recheck: yes\n")
elif failed:
self.trs.write(":global-test-result: FAIL\n")
self.trs.write(":test-global-result: FAIL\n")
@@ -240,11 +253,62 @@ class Driver:
self.trs.write(":global-test-result: SKIP\n")
self.trs.write(":test-global-result: SKIP\n")
self.trs.write(":recheck: no\n")
+ else:
+ self.trs.write(":global-test-result: PASS\n")
+ self.trs.write(":test-global-result: PASS\n")
+ self.trs.write(":recheck: no\n")
if self.errored or failed:
self.trs.write(":copy-in-global-log: yes\n")
# Process result code
- return self.errored and 1 or 0
+ return 0
+
+
+class SimpleDriver(Driver):
+ def __init__(self, args):
+ Driver.__init__(self, args)
+
+ def run(self):
+ returncode = self.execute()
+ if returncode == 0:
+ self.result_pass()
+ self.trs.write(":global-test-result: PASS\n")
+ self.trs.write(":test-global-result: PASS\n")
+ self.trs.write(":recheck: no\n")
+ elif returncode == 77:
+ self.result_skip()
+ self.trs.write(":global-test-result: SKIP\n")
+ self.trs.write(":test-global-result: SKIP\n")
+ self.trs.write(":recheck: no\n")
+ elif returncode == 99:
+ self.report_error()
+ self.trs.write(":global-test-result: ERROR\n")
+ self.trs.write(":test-global-result: ERROR\n")
+ self.trs.write(":copy-in-global-log: yes\n")
+ self.trs.write(":recheck: yes\n")
+ else:
+ self.result_fail()
+ self.trs.write(":global-test-result: FAIL\n")
+ self.trs.write(":test-global-result: FAIL\n")
+ self.trs.write(":copy-in-global-log: yes\n")
+ self.trs.write(":recheck: yes\n")
+
+ # Process result code
+ return 0
+
+
+class MissingDriver(Driver):
+ def __init__(self, args):
+ Driver.__init__(self, args)
+ self.missing = args.missing
+
+ def run(self):
+ self.result_skip("skipping due to: ", self.missing)
+ self.trs.write(":global-test-result: SKIP\n")
+ self.trs.write(":test-global-result: SKIP\n")
+ self.trs.write(":recheck: no\n")
+ return 0
+
class YesNoAction(argparse.Action):
def __init__(self, option_strings, dest, **kwargs):
@@ -256,8 +320,13 @@ class YesNoAction(argparse.Action):
else:
setattr(namespace, self.dest, False)
+
def main(argv):
parser = argparse.ArgumentParser(description='Automake TAP driver')
+ parser.add_argument('--format', metavar='FORMAT', choices=[ "simple", "tap" ],
+ default="simple", help='The type of test to drive')
+ parser.add_argument('--missing', metavar="TOOL", nargs='?',
+ help="Force the test to skip due to missing tool")
parser.add_argument('--test-name', metavar='NAME',
help='The name of the test')
parser.add_argument('--log-file', metavar='PATH.log', required=True,
@@ -276,8 +345,12 @@ def main(argv):
if not args.test_name:
args.test_name = os.path.basename(args.command[0])
-
- driver = Driver(args.command, args)
+ if args.missing:
+ driver = MissingDriver(args)
+ elif args.format == "simple":
+ driver = SimpleDriver(args)
+ elif args.format == "tap":
+ driver = TapDriver(args)
return driver.run()
if __name__ == "__main__":
diff --git a/build/tap-compiler b/build/tap-gtester
similarity index 92%
rename from build/tap-compiler
rename to build/tap-gtester
index 76b3171..ff7506a 100755
--- a/build/tap-compiler
+++ b/build/tap-gtester
@@ -80,7 +80,8 @@ class GTestCompiler(NullCompiler):
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)
+ 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)
@@ -97,7 +98,8 @@ class GTestCompiler(NullCompiler):
output += proc.stdout.read()
proc.wait()
if proc.returncode:
- raise subprocess.CalledProcessError(proc.returncode, self.command)
+ 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("/"):
@@ -130,14 +132,14 @@ class GTestCompiler(NullCompiler):
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 ]:
+ 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" ],
+ 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)')
@@ -149,21 +151,21 @@ def main(argv):
cmd = args.command
proc = None
- if format in ["auto", "GTest"]:
+ 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"
+ format = "gtest"
else:
- format = "TAP"
+ format = "tap"
else:
proc = subprocess.Popen(cmd, close_fds=True, stdout=subprocess.PIPE)
- if format == "GTest":
+ if format == "gtest":
compiler = GTestCompiler(cmd)
- elif format == "TAP":
+ elif format == "tap":
compiler = NullCompiler(cmd)
else:
assert False, "not reached"
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]