blob: 5c83d683303c2c313cfca5b76f8794e7896b7d7b [file] [log] [blame]
import sys
import os
from buildbot.steps import shell
from buildbot.status import builder
from buildbot.process import buildstep
class AnalyzerCompareCommand(shell.ShellCommand):
"""Command suitable for displaying a comparison of two static analyzer
runs, as output by the clang 'utils/analyzer/CmpRun' tool."""
class Observer(buildstep.LogLineObserver):
def __init__(self):
buildstep.LogLineObserver.__init__(self)
# Counts of various reports.
self.num_reports = None
self.num_added = 0
self.num_removed = 0
self.num_changed = 0
# Reports to notify the user about; a list of tuples of (title,
# name, html-report).
self.reports = []
# Lines we couldn't parse.
self.invalid_lines = []
# Make sure we get all the data.
self.setMaxLineLength(sys.maxint)
def outLineReceived(self, line):
"""This is called once with each line of the test log."""
# Ignore empty lines.
line = line.strip()
if not line:
return
# Everything else should be eval()able.
try:
data = eval(line)
key = data[0]
except:
self.invalid_lines.append(line)
return
# FIXME: Improve error checking.
if key == 'ADDED':
_,name,report = data
self.num_added += 1
self.reports.append(('added', str(name), str(report)))
elif key == 'REMOVED':
_,name,report = data
self.num_removed += 1
self.reports.append(('removed', str(name), str(report)))
elif key == 'CHANGED':
_,name,old_name,report,old_report = data
self.num_removed += 1
self.reports.append(('modified', str(name), str(report)))
elif key == 'TOTAL':
if self.num_reports is not None:
self.invalid_lines.append(line)
return
_,count = data
self.num_reports = count
else:
self.invalid_lines.append(line)
def __init__(self, **kwargs):
shell.ShellCommand.__init__(self, **kwargs)
self.observer = AnalyzerCompareCommand.Observer()
self.addLogObserver('comparison-data', self.observer)
def getText(self, cmd, results):
basic_info = self.describe(True)
added = self.observer.num_added
removed = self.observer.num_removed
changed = self.observer.num_changed
total = self.observer.num_reports
if total is not None:
basic_info.append('%d reports' % total)
for name,count in (("added", self.observer.num_added),
("removed", self.observer.num_removed),
("changed", self.observer.num_changed)):
if count:
basic_info.append('%d %s' % (count, name))
return basic_info
def createSummary(self, log):
# Add the "interesting" reports.
for title,name,data in self.observer.reports:
self.addHTMLLog("%s:%s" % (title, os.path.basename(name)), data)
def evaluateCommand(self, cmd):
# Always fail if the command itself failed.
if cmd.rc != 0:
return builder.FAILURE
# Warn about added reports.
if self.observer.num_added:
return builder.WARNINGS
return builder.SUCCESS