diff options
author | Peter Boström <pbos@webrtc.org> | 2015-05-21 13:25:28 +0200 |
---|---|---|
committer | Peter Boström <pbos@webrtc.org> | 2015-05-21 11:25:15 +0000 |
commit | 280ed1149312a479c2186bc2f4dfabcb49f7a593 (patch) | |
tree | c86c333e9d33c5fcbc05761d00fb22ab380008fb | |
parent | 848d5248799c58ca0128184e38588d8587069bc0 (diff) | |
download | webrtc-280ed1149312a479c2186bc2f4dfabcb49f7a593.tar.gz |
Roll gtest-parallel.
Includes modifications by kwiberg@ to reduce line spam by not printing
all passing tests and running previously-failing tests first.
BUG=
R=kwiberg@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/47279004
Cr-Commit-Position: refs/heads/master@{#9248}
-rw-r--r-- | third_party/gtest-parallel/README.webrtc | 2 | ||||
-rwxr-xr-x | third_party/gtest-parallel/gtest-parallel | 73 |
2 files changed, 59 insertions, 16 deletions
diff --git a/third_party/gtest-parallel/README.webrtc b/third_party/gtest-parallel/README.webrtc index f6c935a7e8..acea04fb6e 100644 --- a/third_party/gtest-parallel/README.webrtc +++ b/third_party/gtest-parallel/README.webrtc @@ -1,5 +1,5 @@ URL: https://github.com/google/gtest-parallel -Version: 3405a00ea6661d39f416faf7ccddf3c05fbfe19c +Version: c0f8ded77566c657ccc7f745fd9cb070750cccf8 License: Apache 2.0 License File: LICENSE diff --git a/third_party/gtest-parallel/gtest-parallel b/third_party/gtest-parallel/gtest-parallel index 21c6ee0b30..0be59e4b4e 100755 --- a/third_party/gtest-parallel/gtest-parallel +++ b/third_party/gtest-parallel/gtest-parallel @@ -23,8 +23,46 @@ import threading import time import zlib +# Return the width of the terminal, or None if it couldn't be +# determined (e.g. because we're not being run interactively). +def term_width(out): + if not out.isatty(): + return None + try: + p = subprocess.Popen(["stty", "size"], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + (out, err) = p.communicate() + if p.returncode != 0 or err: + return None + return int(out.split()[1]) + except (IndexError, OSError, ValueError): + return None + +# Output transient and permanent lines of text. If several transient +# lines are written in sequence, the new will overwrite the old. We +# use this to ensure that lots of unimportant info (tests passing) +# won't drown out important info (tests failing). +class Outputter(object): + def __init__(self, out_file): + self.__out_file = out_file + self.__previous_line_was_transient = False + self.__width = term_width(out_file) # Line width, or None if not a tty. + def transient_line(self, msg): + if self.__width is None: + self.__out_file.write(msg + "\n") + else: + self.__out_file.write("\r" + msg[:self.__width].ljust(self.__width)) + self.__previous_line_was_transient = True + def permanent_line(self, msg): + if self.__previous_line_was_transient: + self.__out_file.write("\n") + self.__previous_line_was_transient = False + self.__out_file.write(msg + "\n") + stdout_lock = threading.Lock() + class FilterFormat: + out = Outputter(sys.stdout) total_tests = 0 finished_tests = 0 @@ -33,10 +71,9 @@ class FilterFormat: failures = [] def print_test_status(self, last_finished_test, time_ms): - print "[%d/%d] %s (%d ms)" % (self.finished_tests, - self.total_tests, - last_finished_test, - time_ms) + self.out.transient_line("[%d/%d] %s (%d ms)" + % (self.finished_tests, self.total_tests, + last_finished_test, time_ms)) def handle_meta(self, job_id, args): (command, arg) = args.split(' ', 1) @@ -52,12 +89,13 @@ class FilterFormat: if exit_code != 0: self.failures.append(self.tests[job_id]) for line in self.outputs[job_id]: - print line - print "[%d/%d] %s returned/aborted with exit code %d (%d ms)" \ - % (self.finished_tests, self.total_tests, test, exit_code, time_ms) + self.out.permanent_line(line) + self.out.permanent_line( + "[%d/%d] %s returned/aborted with exit code %d (%d ms)" + % (self.finished_tests, self.total_tests, test, exit_code, time_ms)) elif command == "TESTCNT": self.total_tests = int(arg.split(' ', 1)[1]) - print "[0/%d] Running tests...\r" % self.total_tests, + self.out.transient_line("[0/%d] Running tests..." % self.total_tests) def add_stdout(self, job_id, output): self.outputs[job_id].append(output) @@ -74,9 +112,10 @@ class FilterFormat: def end(self): if self.failures: - print "FAILED TESTS (%d/%d):" % (len(self.failures), self.total_tests) + self.out.permanent_line("FAILED TESTS (%d/%d):" + % (len(self.failures), self.total_tests)) for (binary, test) in self.failures: - print " ", binary + ": " + test + self.out.permanent_line(" " + binary + ": " + test) class RawFormat: def log(self, line): @@ -221,7 +260,10 @@ logger.log(str(-1) + ': TESTCNT ' + ' ' + str(len(tests))) exit_code = 0 -# Run the specified job. Returns the elapsed time in milliseconds. +# Run the specified job. Return the elapsed time in milliseconds if +# the job succeeds, or a very large number (larger than any reasonable +# elapsed time) if the job fails. (This ensures that failing tests +# will run first the next time.) def run_job((command, job_id, test)): begin = time.time() sub = subprocess.Popen(command + ['--gtest_filter=' + test] + @@ -238,10 +280,11 @@ def run_job((command, job_id, test)): code = sub.wait() runtime_ms = int(1000 * (time.time() - begin)) logger.log("%s: EXIT %s %d" % (job_id, code, runtime_ms)) - if code != 0: - global exit_code - exit_code = code - return runtime_ms + if code == 0: + return runtime_ms + global exit_code + exit_code = code + return sys.maxint def worker(): global job_id |