diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Makefile.am | 54 | ||||
-rw-r--r-- | build/Makefile.am | 34 | ||||
-rwxr-xr-x | build/tap-driver | 215 | ||||
-rwxr-xr-x | build/tap-gtester (renamed from build/tap-compiler) | 20 |
5 files changed, 197 insertions, 127 deletions
@@ -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/Makefile.am b/build/Makefile.am deleted file mode 100644 index 20cfa35..0000000 --- a/build/Makefile.am +++ /dev/null @@ -1,34 +0,0 @@ -# included in top-level Makefile.am - -VALGRIND_CONTRIB = \ - build/valgrind/valgrind.h \ - build/valgrind/memcheck.h - -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: $(SUPPRESSIONS) - $(AM_V_GEN) sh -c "cd $(srcdir) && cat $(SUPPRESSIONS)" > $@ - -EXTRA_DIST += \ - $(VALGRIND_CONTRIB) \ - $(SUPPRESSIONS) \ - build/enum-template.c \ - build/enum-template.h \ - build/g-ir-unbreak.xsl \ - build/tap-driver \ - build/tap-compiler - -all-local: valgrind-suppressions - -CLEANFILES += \ - coverage \ - coverage.info \ - valgrind-suppressions 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 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" |