Skip to content

Commit cdaa2bc

Browse files
author
buildbot
committed
Updated buildbot from 0.8 to 2.7, transitioned to Python 3, and added some convenience scripts.
- Legacy-Id: 17657
1 parent 19a26dc commit cdaa2bc

File tree

17 files changed

+597
-487
lines changed

17 files changed

+597
-487
lines changed
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
# Copyright The IETF Trust 2015-2020, All Rights Reserved
2+
# -*- coding: utf-8 -*-
3+
4+
import re
5+
6+
from buildbot.plugins import steps
7+
8+
class TestCrawlerShellCommand(steps.WarningCountingShellCommand):
9+
name = "testcrawl"
10+
haltOnFailure = 1
11+
flunkOnFailure = 1
12+
descriptionDone = ["test crawler"]
13+
command=["bin/test-crawl"]
14+
15+
warningPatterns = {
16+
"exceptions": "^(Traceback| File| |.*Error|.*Exception)",
17+
"failed": " FAIL ",
18+
"warnings": " WARN",
19+
"slow": " SLOW",
20+
"invalid_html": " invalid html:",
21+
}
22+
23+
logline = "^ *(?P<elapsed>\d+:\d+:\d+) +(?P<pages>\d+) +(?P<queue>\d+) +(?P<result>\d+) +(?P<runtime>\d+.\d+)s +(?P<message>.+)"
24+
25+
def setTestResults(self, **kwargs):
26+
"""
27+
Called by subclasses to set the relevant statistics; this actually
28+
adds to any statistics already present
29+
"""
30+
for kw in kwargs:
31+
value = kwargs[kw]
32+
if value.isdigit():
33+
# Counter
34+
value = int(value)
35+
value += self.step_status.getStatistic(kw, 0)
36+
elif re.search("^[0-9]+\.[0-9]+$", value):
37+
# Runtime
38+
value = float(value)
39+
value += self.step_status.getStatistic(kw, 0)
40+
else:
41+
# This is a percentage, and we can't add them
42+
pass
43+
self.step_status.setStatistic(kw, value)
44+
45+
def createSummary(self, log):
46+
"""
47+
Match log lines against warningPattern.
48+
49+
Warnings are collected into another log for this step, and the
50+
build-wide 'warnings-count' is updated."""
51+
52+
warnings = {}
53+
wregex = {}
54+
55+
regex_class = re.compile("").__class__
56+
57+
if not isinstance(self.logline, regex_class):
58+
self.logline = re.compile(self.logline)
59+
60+
for key in self.warningPatterns:
61+
warnings[key] = []
62+
pattern = self.warningPatterns[key]
63+
if not isinstance(pattern, regex_class):
64+
wregex[key] = re.compile(pattern)
65+
else:
66+
wregex[key] = pattern
67+
68+
# Count matches to the various warning patterns
69+
for line in log.getText().split("\n"):
70+
for key in wregex:
71+
match = re.search(wregex[key], line)
72+
if match:
73+
warnings[key].append(line)
74+
if re.search(self.logline, line):
75+
last_line = line
76+
77+
# If there were any warnings, make the log if lines with warnings
78+
# available
79+
for key in warnings:
80+
if len(warnings[key]) > 0:
81+
self.addCompleteLog("%s (%d)" % (key, len(warnings[key])),
82+
"\n".join(warnings[key]) + "\n")
83+
self.step_status.setStatistic(key, len(warnings[key]))
84+
self.setProperty(key, len(warnings[key]), "TestCrawlerShellCommand")
85+
86+
match = re.search(self.logline, last_line)
87+
for key in ['elapsed', 'pages']:
88+
info = match.group(key)
89+
self.step_status.setStatistic(key, info)
90+
self.setProperty(key, info, "TestCrawlerShellCommand")
91+
92+
def describe(self, done=False):
93+
description = steps.WarningCountingShellCommand.describe(self, done)
94+
if done:
95+
description = description[:] # make a private copy
96+
for name in ["time", "elapsed", "pages", "failed", "warnings", "slow", "invalid_html", ]:
97+
if name in self.step_status.statistics:
98+
value = self.step_status.getStatistic(name)
99+
displayName = name.replace('_', ' ')
100+
# special case. Mph.
101+
if type(value) is float: # this is run-time
102+
description.append('%s: %.2fs' % (displayName, value))
103+
elif type(value) is int:
104+
description.append('%s: %d' % (displayName, value))
105+
else:
106+
description.append('%s: %s' % (displayName, value))
107+
return description
108+
109+
110+
class DjangoTest(steps.WarningCountingShellCommand):
111+
112+
name = "test"
113+
warnOnFailure = 1
114+
description = ["testing"]
115+
descriptionDone = ["test"]
116+
command = ["python", "-m", "unittest", "discover"]
117+
118+
regexPatterns = {
119+
"tests": "Ran (\d+) tests in [0-9.]+s",
120+
"time": "Ran \d+ tests in ([0-9.]+)s",
121+
"skipped": "(?:OK|FAILED).*skipped=(\d+)",
122+
"failed": "FAILED.*failures=(\d+)",
123+
"errors": "FAILED.*errors=(\d+)",
124+
"template_coverage":" +Template coverage: +([0-9.]+%)",
125+
"url_coverage": " +Url coverage: +([0-9.]+%)",
126+
"code_coverage": " +Code coverage: +([0-9.]+%)",
127+
}
128+
129+
def setTestResults(self, **kwargs):
130+
"""
131+
Called by subclasses to set the relevant statistics; this actually
132+
adds to any statistics already present
133+
"""
134+
for kw in kwargs:
135+
value = kwargs[kw]
136+
if value.isdigit():
137+
# Counter
138+
value = int(value)
139+
value += self.step_status.getStatistic(kw, 0)
140+
elif re.search("^[0-9]+\.[0-9]+$", value):
141+
# Runtime
142+
value = float(value)
143+
value += self.step_status.getStatistic(kw, 0)
144+
else:
145+
# This is a percentage, and we can't add them
146+
pass
147+
self.step_status.setStatistic(kw, value)
148+
149+
def createSummary(self, log):
150+
info = {}
151+
for line in log.getText().split("\n"):
152+
for key in self.regexPatterns:
153+
regex = self.regexPatterns[key]
154+
match = re.search(regex, line)
155+
if match:
156+
info[key] = match.group(1)
157+
self.setTestResults(**info)
158+
159+
def describe(self, done=False):
160+
description = steps.WarningCountingShellCommand.describe(self, done)
161+
if done:
162+
description = description[:] # make a private copy
163+
self.step_status.statistics["passed"] = (
164+
self.step_status.getStatistic("tests",0) -
165+
self.step_status.getStatistic("skipped",0) -
166+
self.step_status.getStatistic("failed",0) -
167+
self.step_status.getStatistic("errors",0))
168+
for name in ["time", "tests", "passed", "skipped", "failed", "errors", "template_coverage", "url_coverage", "code_coverage", ]:
169+
if name in self.step_status.statistics:
170+
value = self.step_status.getStatistic(name)
171+
displayName = name.replace('_', ' ')
172+
# special case. Mph.
173+
if displayName == 'template coverage':
174+
displayName = 'templ. coverage'
175+
if type(value) is float: # this is run-time
176+
description.append('%s: %.2fs' % (displayName, value))
177+
elif type(value) is int:
178+
description.append('%s: %d' % (displayName, value))
179+
else:
180+
description.append('%s: %s' % (displayName, value))
181+
return description

0 commit comments

Comments
 (0)