[llvm-commits] [zorg] r101577 - in /zorg/trunk/zorg/buildbot/commands: LitTestCommand.py StandardizedTest.py
Daniel Dunbar
daniel at zuster.org
Fri Apr 16 16:36:10 PDT 2010
Author: ddunbar
Date: Fri Apr 16 18:36:10 2010
New Revision: 101577
URL: http://llvm.org/viewvc/llvm-project?rev=101577&view=rev
Log:
buildbot: Add a new StandardizedTest test command, which serves as a base class
for test steps that want to parse log files and bin the results into things like
PASS, FAIL, etc.
Also, add a new LitTestCommand based on this.
Added:
zorg/trunk/zorg/buildbot/commands/LitTestCommand.py
zorg/trunk/zorg/buildbot/commands/StandardizedTest.py
Added: zorg/trunk/zorg/buildbot/commands/LitTestCommand.py
URL: http://llvm.org/viewvc/llvm-project/zorg/trunk/zorg/buildbot/commands/LitTestCommand.py?rev=101577&view=auto
==============================================================================
--- zorg/trunk/zorg/buildbot/commands/LitTestCommand.py (added)
+++ zorg/trunk/zorg/buildbot/commands/LitTestCommand.py Fri Apr 16 18:36:10 2010
@@ -0,0 +1,50 @@
+import re
+import StandardizedTest
+
+class LitTestCommand(StandardizedTest.StandardizedTest):
+ kTestLineRE = re.compile(r'([^ ]*): (.*) \(.*.*\)')
+ kTestFailureLogStartRE = re.compile(r"""\*{4,80} TEST '(.*)' .*""")
+ kTestFailureLogStopRE = re.compile(r"""\*{10,80}""")
+
+ def parseLog(self, lines):
+ results = []
+ results_by_name = {}
+ failureLogs = []
+ lines = self.getLog('stdio').readlines()
+
+ it = iter(lines)
+ inFailure = None
+ for ln in it:
+ # See if we are inside a failure log.
+ if inFailure:
+ inFailure[1].append(ln)
+ if self.kTestFailureLogStopRE.match(ln):
+ name,log = inFailure
+ if name not in results_by_name:
+ raise ValueError,'Invalid log result with no status line!'
+ results_by_name[name][2] = ''.join(log) + '\n'
+ inFailure = None
+ continue
+
+ ln = ln.strip()
+ if not ln:
+ continue
+
+ # Check for test failure logs.
+ m = self.kTestFailureLogStartRE.match(ln)
+ if m:
+ inFailure = (m.group(1), [ln])
+ continue
+
+ # Otherwise expect a test status line.
+ m = self.kTestLineRE.match(ln)
+ if m:
+ code, name = m.group(1),m.group(2)
+ results.append( [code, name, None] )
+ results_by_name[name] = results[-1]
+
+ if inFailure:
+ raise ValueError,("Unexpected clang test running output, "
+ "unterminated failure log!")
+
+ return results
Added: zorg/trunk/zorg/buildbot/commands/StandardizedTest.py
URL: http://llvm.org/viewvc/llvm-project/zorg/trunk/zorg/buildbot/commands/StandardizedTest.py?rev=101577&view=auto
==============================================================================
--- zorg/trunk/zorg/buildbot/commands/StandardizedTest.py (added)
+++ zorg/trunk/zorg/buildbot/commands/StandardizedTest.py Fri Apr 16 18:36:10 2010
@@ -0,0 +1,95 @@
+import re
+import buildbot
+import buildbot.status.builder
+import buildbot.steps.shell
+
+class StandardizedTest(buildbot.steps.shell.Test):
+ # FIXME: We should process things in a test observer instead of at the end.
+
+ knownCodes = ['FAIL', 'XFAIL', 'PASS', 'XPASS',
+ 'UNRESOLVED', 'UNSUPPORTED']
+ failingCodes = set(['FAIL', 'XPASS', 'UNRESOLVED'])
+ warningCodes = set(['IGN PASS', 'IGN XFAIL'])
+
+ # The list of all possible codes, including ignored codes. This is the
+ # display order, as well.
+ allKnownCodes = knownCodes + ['IGN ' + c for c in knownCodes]
+
+ testLogName = 'stdio'
+
+ def __init__(self, ignore=[], max_logs=20,
+ *args, **kwargs):
+ buildbot.steps.shell.Test.__init__(self, *args, **kwargs)
+
+ self.ignoredTests = set(ignore)
+ self.maxLogs = int(max_logs)
+ self.addFactoryArguments(ignore=list(ignore))
+ self.addFactoryArguments(max_logs=max_logs)
+
+ def parseLog(self, log_lines):
+ """parseLog(log_lines) -> [(result_code, test_name, test_log), ...]"""
+ abstract
+
+ def evaluateCommand(self, cmd):
+ # Always fail if the command itself failed.
+ if cmd.rc != 0:
+ return buildbot.status.builder.FAILURE
+
+ results_by_code = {}
+ logs = []
+ lines = self.getLog(self.testLogName).readlines()
+ for result,test,log in self.parseLog(lines):
+ if result not in self.knownCodes:
+ raise ValueError,'test command return invalid result code!'
+
+ # Convert externally expected failures.
+ if test in self.ignoredTests:
+ result = 'IGN ' + result
+
+ if result not in results_by_code:
+ results_by_code[result] = set()
+
+ results_by_code[result].add(test)
+
+ # Add logs for failures.
+ if result in self.failingCodes and len(logs) < self.maxLogs:
+ if log is not None and log.strip():
+ logs.append((test, log))
+
+ # Summarize result counts.
+ total = failed = passed = warnings = 0
+ for code in self.allKnownCodes:
+ results = results_by_code.get(code)
+ if not results:
+ continue
+
+ total += len(results)
+ if code in self.failingCodes:
+ failed += len(results)
+ elif code in self.warningCodes:
+ warnings += len(results)
+ else:
+ passed += len(results)
+
+ # Add a list of the tests in each category, for everything except
+ # PASS.
+ if code != 'PASS':
+ results = list(results)
+ results.sort()
+ self.addCompleteLog('tests.%s' % code,
+ '\n'.join(results) + '\n')
+
+ self.setTestResults(total=total, failed=failed,
+ passed=passed, warnings=warnings)
+
+ # Add the logs.
+ logs.sort()
+ for test, log in logs:
+ self.addCompleteLog(test, log)
+
+ if failed:
+ return buildbot.status.builder.FAILURE
+ if warnings:
+ return buildbot.status.builder.WARNINGS
+
+ return buildbot.status.builder.SUCCESS
More information about the llvm-commits
mailing list