Recognize crashed tests as failures in sharding_supervisor

Added some regexes and shard output processing

BUG=92653
TEST=crashed tests are shown in the summary


Review URL: http://codereview.chromium.org/7650012

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@96999 0039d316-1c4b-4281-b951-d872f2087c98
parent b31d6314
...@@ -81,21 +81,37 @@ class ShardRunner(threading.Thread): ...@@ -81,21 +81,37 @@ class ShardRunner(threading.Thread):
counter: Called to get the next shard index to run. counter: Called to get the next shard index to run.
""" """
def __init__(self, supervisor, counter, test_fail, test_timeout): def __init__(self, supervisor, counter, test_start, test_ok, test_fail):
"""Inits ShardRunner with a supervisor and counter.""" """Inits ShardRunner with a supervisor and counter."""
threading.Thread.__init__(self) threading.Thread.__init__(self)
self.supervisor = supervisor self.supervisor = supervisor
self.counter = counter self.counter = counter
self.test_start = test_start
self.test_ok = test_ok
self.test_fail = test_fail self.test_fail = test_fail
self.test_timeout = test_timeout self.current_test = ""
def SearchForFailure(self, regex, prefix, line, description): def ReportFailure(self, description, prefix, test_name):
results = regex.search(line) log_line = "%s: %s%s\n" % (description, prefix, test_name)
self.supervisor.LogLineFailure(log_line)
def ProcessLine(self, prefix, line):
results = self.test_start.search(line)
if results:
if self.current_test:
self.ReportFailure("INCOMPLETE", prefix, self.current_test)
self.current_test = results.group(1)
return
results = self.test_ok.search(line)
if results:
self.current_test = ""
return
results = self.test_fail.search(line)
if results: if results:
log_line = "%s: %s%s\n" % (description, prefix, results.group(1)) self.ReportFailure("FAILED", prefix, results.group(1))
self.supervisor.LogLineFailure(log_line) self.current_test = ""
return True
return False
def run(self): def run(self):
"""Runs shards and outputs the results. """Runs shards and outputs the results.
...@@ -124,9 +140,7 @@ class ShardRunner(threading.Thread): ...@@ -124,9 +140,7 @@ class ShardRunner(threading.Thread):
line = chars.getvalue() line = chars.getvalue()
if not line and not shard_running: if not line and not shard_running:
break break
if not self.SearchForFailure( self.ProcessLine(prefix, line)
self.test_fail, prefix, line, "FAILED"):
self.SearchForFailure(self.test_timeout, prefix, line, "TIMEOUT")
line = prefix + line line = prefix + line
self.supervisor.LogOutputLine(index, line) self.supervisor.LogOutputLine(index, line)
chars.close() chars.close()
...@@ -185,25 +199,23 @@ class ShardingSupervisor(object): ...@@ -185,25 +199,23 @@ class ShardingSupervisor(object):
test_name_regex = r"((\w+/)?\w+\.\w+(/\d+)?)" test_name_regex = r"((\w+/)?\w+\.\w+(/\d+)?)"
# Regex for filtering out ANSI escape codes when using color. # Regex for filtering out ANSI escape codes when using color.
ansi_code_regex = r"(?:\x1b\[.*?[a-zA-Z])?" ansi_regex = r"(?:\x1b\[.*?[a-zA-Z])?"
test_start = re.compile(
ansi_regex + r"\[\s+RUN\s+\] " + ansi_regex + test_name_regex)
test_ok = re.compile(
ansi_regex + r"\[\s+OK\s+\] " + ansi_regex + test_name_regex)
test_fail = re.compile( test_fail = re.compile(
ansi_code_regex + "\[\s+FAILED\s+\] " + ansi_code_regex + ansi_regex + r"\[\s+FAILED\s+\] " + ansi_regex + test_name_regex)
test_name_regex)
test_timeout = re.compile(
"Test timeout \([0-9]+ ms\) exceeded for " + test_name_regex)
workers = [] workers = []
counter = Queue.Queue() counter = Queue.Queue()
for i in range(self.num_shards): for i in range(self.num_shards):
counter.put(i) counter.put(i)
# Disable stdout buffering to read shard output one character at a time.
# This allows for shard crashes that do not end with a "\n".
sys.stdout = os.fdopen(sys.stdout.fileno(), "w", 0)
for i in range(self.num_runs): for i in range(self.num_runs):
worker = ShardRunner(self, counter, test_fail, test_timeout) worker = ShardRunner(
self, counter, test_start, test_ok, test_fail)
worker.start() worker.start()
workers.append(worker) workers.append(worker)
if self.reorder: if self.reorder:
...@@ -212,10 +224,7 @@ class ShardingSupervisor(object): ...@@ -212,10 +224,7 @@ class ShardingSupervisor(object):
for worker in workers: for worker in workers:
worker.join() worker.join()
# Re-enable stdout buffering. return self.PrintSummary(self.failure_log)
sys.stdout = sys.__stdout__
return self.PrintSummary()
def LogLineFailure(self, line): def LogLineFailure(self, line):
"""Saves a line in the failure log to be printed at the end. """Saves a line in the failure log to be printed at the end.
...@@ -251,7 +260,7 @@ class ShardingSupervisor(object): ...@@ -251,7 +260,7 @@ class ShardingSupervisor(object):
def ShardIndexCompleted(self, index): def ShardIndexCompleted(self, index):
self.shard_output[index].put(self.SHARD_COMPLETED) self.shard_output[index].put(self.SHARD_COMPLETED)
def PrintSummary(self): def PrintSummary(self, failed_tests):
"""Prints a summary of the test results. """Prints a summary of the test results.
If any shards had failing tests, the list is sorted and printed. Then all If any shards had failing tests, the list is sorted and printed. Then all
...@@ -264,25 +273,26 @@ class ShardingSupervisor(object): ...@@ -264,25 +273,26 @@ class ShardingSupervisor(object):
num_failed = len(self.failed_shards) num_failed = len(self.failed_shards)
if num_failed > 0: if num_failed > 0:
self.failed_shards.sort() self.failed_shards.sort()
if self.color: self.WriteText(sys.stderr,
sys.stderr.write("\x1b[1;5;31m") "FAILED SHARDS: %s\n" % str(self.failed_shards),
sys.stderr.write("SHARDS THAT FAILED: %s\n" % str(self.failed_shards)) "\x1b[1;5;31m")
else: else:
if self.color: self.WriteText(sys.stderr, "ALL SHARDS PASSED!\n", "\x1b[1;5;32m")
sys.stderr.write("\x1b[1;5;32m") if failed_tests:
sys.stderr.write("ALL SHARDS PASSED!\n") self.WriteText(sys.stderr, "FAILED TESTS:\n", "\x1b[1;5;31m")
if self.failure_log: for line in failed_tests:
if self.color:
sys.stderr.write("\x1b[1;5;31m")
sys.stderr.write("TESTS THAT DID NOT PASS:\n")
if self.color:
sys.stderr.write("\x1b[m")
for line in self.failure_log:
sys.stderr.write(line) sys.stderr.write(line)
if self.color: if self.color:
sys.stderr.write("\x1b[m") sys.stderr.write("\x1b[m")
return num_failed return num_failed
def WriteText(self, pipe, text, ansi):
if self.color:
pipe.write(ansi)
pipe.write(text)
if self.color:
pipe.write("\x1b[m")
def main(): def main():
parser = optparse.OptionParser(usage=SS_USAGE) parser = optparse.OptionParser(usage=SS_USAGE)
...@@ -293,7 +303,8 @@ def main(): ...@@ -293,7 +303,8 @@ def main():
"-r", "--runs_per_core", type="int", default=SS_DEFAULT_RUNS_PER_CORE, "-r", "--runs_per_core", type="int", default=SS_DEFAULT_RUNS_PER_CORE,
help="number of shards to run in parallel per CPU") help="number of shards to run in parallel per CPU")
parser.add_option( parser.add_option(
"-c", "--color", action="store_true", default=sys.stdout.isatty(), "-c", "--color", action="store_true",
default=sys.platform != "win32" and sys.stdout.isatty(),
help="force color output, also used by gtest if --gtest_color is not" help="force color output, also used by gtest if --gtest_color is not"
" specified") " specified")
parser.add_option( parser.add_option(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment