Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(463)

Side by Side Diff: third_party/WebKit/Tools/Scripts/webkitpy/common/net/buildbot_unittest.py

Issue 2112133002: Greatly simplify buildbot module and remove usage of master name. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebased Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 # Copyright (C) 2009 Google Inc. All rights reserved. 1 # Copyright (C) 2009 Google Inc. All rights reserved.
2 # 2 #
3 # Redistribution and use in source and binary forms, with or without 3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions are 4 # modification, are permitted provided that the following conditions are
5 # met: 5 # met:
6 # 6 #
7 # * Redistributions of source code must retain the above copyright 7 # * Redistributions of source code must retain the above copyright
8 # notice, this list of conditions and the following disclaimer. 8 # notice, this list of conditions and the following disclaimer.
9 # * Redistributions in binary form must reproduce the above 9 # * Redistributions in binary form must reproduce the above
10 # copyright notice, this list of conditions and the following disclaimer 10 # copyright notice, this list of conditions and the following disclaimer
(...skipping 10 matching lines...) Expand all
21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 28
29 import unittest 29 import unittest
30 30
31 from webkitpy.common.net.buildbot import Build
32 from webkitpy.common.net.buildbot import BuildBot 31 from webkitpy.common.net.buildbot import BuildBot
33 from webkitpy.common.net.buildbot import Builder
34 from webkitpy.common.net.layouttestresults import LayoutTestResults 32 from webkitpy.common.net.layouttestresults import LayoutTestResults
35 from webkitpy.layout_tests.models import test_failures
36 from webkitpy.layout_tests.models import test_results
37 from webkitpy.thirdparty.BeautifulSoup import BeautifulSoup
38 33
39 34
40 class BuilderTest(unittest.TestCase): 35 class BuilderTest(unittest.TestCase):
41 36
42 def _mock_test_result(self, testname):
43 return test_results.TestResult(testname, [test_failures.FailureTextMisma tch()])
44
45 def setUp(self): 37 def setUp(self):
46 self.buildbot = BuildBot() 38 self.buildbot = BuildBot()
47 self.builder = Builder(u"Test Builder \u2661", self.buildbot)
48
49 def _mock_fetch_build(build_number):
50 build = Build(
51 builder=self.builder,
52 build_number=build_number,
53 revision=build_number + 1000,
54 is_green=build_number < 4)
55 return build
56
57 self.builder._fetch_build = _mock_fetch_build
58 39
59 def test_latest_layout_test_results(self): 40 def test_latest_layout_test_results(self):
60 self.builder.fetch_layout_test_results = lambda results_url: LayoutTestR esults(None) 41 builder = BuildBot().builder_with_name('WebKit Mac10.8 (dbg)')
61 self.builder.accumulated_results_url = lambda: "http://dummy_url.org" 42 builder.fetch_layout_test_results = lambda _: LayoutTestResults(None)
62 self.assertTrue(self.builder.latest_layout_test_results()) 43 self.assertTrue(builder.latest_layout_test_results())
63
64 def test_build_caching(self):
65 self.assertEqual(self.builder.build(10), self.builder.build(10))
66
67 def test_build_and_revision_for_filename(self):
68 expectations = {
69 "r47483 (1)/": (47483, 1),
70 "r47483 (1).zip": (47483, 1),
71 "random junk": None,
72 }
73 for filename, revision_and_build in expectations.items():
74 self.assertEqual(self.builder._revision_and_build_for_filename(filen ame), revision_and_build)
75
76 def test_file_info_list_to_revision_to_build_list(self):
77 file_info_list = [
78 {"filename": "r47483 (1)/"},
79 {"filename": "r47483 (1).zip"},
80 {"filename": "random junk"},
81 ]
82 builds_and_revisions_list = [(47483, 1), (47483, 1)]
83 self.assertEqual(self.builder._file_info_list_to_revision_to_build_list( file_info_list), builds_and_revisions_list)
84
85 def test_fetch_build(self):
86 buildbot = BuildBot()
87 builder = Builder(u"Test Builder \u2661", buildbot)
88
89 def mock_fetch_build_dictionary(_, build_number):
90 return {
91 "sourceStamp": {
92 "revision": None, # revision=None means a trunk build start ed from the force-build button on the builder page.
93 },
94 "number": int(build_number),
95 # Intentionally missing the 'results' key, meaning it's a "pass" build.
96 }
97 buildbot.fetch_build_dictionary = mock_fetch_build_dictionary
98 self.assertIsNotNone(builder._fetch_build(1))
99 44
100 def test_results_url(self): 45 def test_results_url(self):
101 builder = BuildBot().builder_with_name('WebKit Mac10.8 (dbg)') 46 builder = BuildBot().builder_with_name('WebKit Mac10.8 (dbg)')
102 self.assertEqual(builder.results_url(), 47 self.assertEqual(
103 'https://storage.googleapis.com/chromium-layout-test-ar chives/WebKit_Mac10_8__dbg_') 48 builder.results_url(),
49 'https://storage.googleapis.com/chromium-layout-test-archives/WebKit _Mac10_8__dbg_')
104 50
105 def test_accumulated_results_url(self): 51 def test_accumulated_results_url(self):
106 builder = BuildBot().builder_with_name('WebKit Mac10.8 (dbg)') 52 builder = BuildBot().builder_with_name('WebKit Mac10.8 (dbg)')
107 self.assertEqual(builder.accumulated_results_url(), 53 self.assertEqual(
108 'https://storage.googleapis.com/chromium-layout-test-ar chives/WebKit_Mac10_8__dbg_/results/layout-test-results') 54 builder.latest_layout_test_results_url(),
55 'https://storage.googleapis.com/chromium-layout-test-archives/WebKit _Mac10_8__dbg_/results/layout-test-results')
109 56
110 57
111 class BuildBotTest(unittest.TestCase): 58 class BuildBotTest(unittest.TestCase):
112 59
113 _example_one_box_status = '''
114 <table>
115 <tr>
116 <td class="box"><a href="builders/Windows%20Debug%20%28Tests%29">Windows Deb ug (Tests)</a></td>
117 <td align="center" class="LastBuild box success"><a href="builders/Windows %20Debug%20%28Tests%29/builds/3693">47380</a><br />build<br />successful</td>
118 <td align="center" class="Activity building">building<br />ETA in<br />~ 1 4 mins<br />at 13:40</td>
119 <tr>
120 <td class="box"><a href="builders/SnowLeopard%20Intel%20Release">SnowLeopard Intel Release</a></td>
121 <td class="LastBuild box" >no build</td>
122 <td align="center" class="Activity building">building<br />< 1 min</td>
123 <tr>
124 <td class="box"><a href="builders/Qt%20Linux%20Release">Qt Linux Release</a> </td>
125 <td align="center" class="LastBuild box failure"><a href="builders/Qt%20Li nux%20Release/builds/654">47383</a><br />failed<br />compile-webkit</td>
126 <td align="center" class="Activity idle">idle<br />3 pending</td>
127 <tr>
128 <td class="box"><a href="builders/Qt%20Windows%2032-bit%20Debug">Qt Windows 32-bit Debug</a></td>
129 <td align="center" class="LastBuild box failure"><a href="builders/Qt%20Wi ndows%2032-bit%20Debug/builds/2090">60563</a><br />failed<br />failed<br />slave <br />lost</td>
130 <td align="center" class="Activity building">building<br />ETA in<br />~ 5 mins<br />at 08:25</td>
131 </table>
132 '''
133 _expected_example_one_box_parsings = [
134 {
135 'is_green': True,
136 'build_number': 3693,
137 'name': u'Windows Debug (Tests)',
138 'built_revision': 47380,
139 'activity': 'building',
140 'pending_builds': 0,
141 },
142 {
143 'is_green': False,
144 'build_number': None,
145 'name': u'SnowLeopard Intel Release',
146 'built_revision': None,
147 'activity': 'building',
148 'pending_builds': 0,
149 },
150 {
151 'is_green': False,
152 'build_number': 654,
153 'name': u'Qt Linux Release',
154 'built_revision': 47383,
155 'activity': 'idle',
156 'pending_builds': 3,
157 },
158 {
159 'is_green': True,
160 'build_number': 2090,
161 'name': u'Qt Windows 32-bit Debug',
162 'built_revision': 60563,
163 'activity': 'building',
164 'pending_builds': 0,
165 },
166 ]
167
168 def test_status_parsing(self):
169 buildbot = BuildBot()
170
171 soup = BeautifulSoup(self._example_one_box_status)
172 status_table = soup.find("table")
173 input_rows = status_table.findAll('tr')
174
175 for x in range(len(input_rows)):
176 status_row = input_rows[x]
177 expected_parsing = self._expected_example_one_box_parsings[x]
178
179 builder = buildbot._parse_builder_status_from_row(status_row)
180
181 # Make sure we aren't parsing more or less than we expect
182 self.assertEqual(builder.keys(), expected_parsing.keys())
183
184 for key, expected_value in expected_parsing.items():
185 self.assertEqual(builder[key], expected_value, ("Builder %d pars e failure for key: %s: Actual='%s' Expected='%s'" % (
186 x, key, builder[key], expected_value)))
187
188 def test_builder_with_name(self): 60 def test_builder_with_name(self):
189 buildbot = BuildBot() 61 buildbot = BuildBot()
190 62
191 builder = buildbot.builder_with_name("Test Builder", master_name='chromi um.webkit') 63 builder = buildbot.builder_with_name('Test Builder')
192 self.assertEqual(builder.name(), "Test Builder") 64 self.assertEqual(builder.name(), 'Test Builder')
193 self.assertEqual(builder.url(), "http://build.chromium.org/p/chromium.we bkit/builders/Test%20Builder") 65 self.assertEqual(builder.results_url(), 'https://storage.googleapis.com/ chromium-layout-test-archives/Test_Builder')
194 self.assertEqual(builder.url_encoded_name(), "Test%20Builder")
195 self.assertEqual(builder.results_url(), "https://storage.googleapis.com/ chromium-layout-test-archives/Test_Builder")
196 66
197 # Override fetch_build_dictionary function to not touch the network.
198 def mock_fetch_build_dictionary(_, build_number):
199 return {
200 "sourceStamp": {
201 "revision": 2 * build_number,
202 },
203 "number": int(build_number),
204 "results": build_number % 2, # 0 means pass
205 }
206
207 buildbot.fetch_build_dictionary = mock_fetch_build_dictionary
208 build = builder.build(10) 67 build = builder.build(10)
209 self.assertEqual(build.builder(), builder) 68 self.assertEqual(build.builder(), builder)
210 self.assertEqual(build.url(), "http://build.chromium.org/p/chromium.webk it/builders/Test%20Builder/builds/10")
211 self.assertEqual( 69 self.assertEqual(
212 build.results_url(), 70 build.results_url(),
213 "https://storage.googleapis.com/chromium-layout-test-archives/Test_B uilder/10/layout-test-results") 71 'https://storage.googleapis.com/chromium-layout-test-archives/Test_B uilder/10/layout-test-results')
214 self.assertEqual(build.revision(), 20)
215 self.assertTrue(build.is_green())
216
217 build = build.previous_build()
218 self.assertEqual(build.builder(), builder)
219 self.assertEqual(build.url(), "http://build.chromium.org/p/chromium.webk it/builders/Test%20Builder/builds/9")
220 self.assertEqual(
221 build.results_url(),
222 "https://storage.googleapis.com/chromium-layout-test-archives/Test_B uilder/9/layout-test-results")
223 self.assertEqual(build.revision(), 18)
224 self.assertFalse(build.is_green())
225
226 self.assertIsNone(builder.build(None))
227
228 _example_directory_listing = '''
229 <h1>Directory listing for /results/SnowLeopard Intel Leaks/</h1>
230
231 <table>
232 <tr class="alt">
233 <th>Filename</th>
234 <th>Size</th>
235 <th>Content type</th>
236 <th>Content encoding</th>
237 </tr>
238 <tr class="directory ">
239 <td><a href="r47483%20%281%29/"><b>r47483 (1)/</b></a></td>
240 <td><b></b></td>
241 <td><b>[Directory]</b></td>
242 <td><b></b></td>
243 </tr>
244 <tr class="file alt">
245 <td><a href="r47484%20%282%29.zip">r47484 (2).zip</a></td>
246 <td>89K</td>
247 <td>[application/zip]</td>
248 <td></td>
249 </tr>
250 '''
251 _expected_files = [
252 {
253 "filename": "r47483 (1)/",
254 "size": "",
255 "type": "[Directory]",
256 "encoding": "",
257 },
258 {
259 "filename": "r47484 (2).zip",
260 "size": "89K",
261 "type": "[application/zip]",
262 "encoding": "",
263 },
264 ]
265
266 def test_parse_build_to_revision_map(self):
267 buildbot = BuildBot()
268 files = buildbot._parse_twisted_directory_listing(self._example_director y_listing)
269 self.assertEqual(self._expected_files, files)
270
271 _fake_builder_page = '''
272 <body>
273 <div class="content">
274 <h1>Some Builder</h1>
275 <p>(<a href="../waterfall?show=Some Builder">view in waterfall</a>)</p>
276 <div class="column">
277 <h2>Recent Builds:</h2>
278 <table class="info">
279 <tr>
280 <th>Time</th>
281 <th>Revision</th>
282 <th>Result</th> <th>Build #</th>
283 <th>Info</th>
284 </tr>
285 <tr class="alt">
286 <td>Jan 10 15:49</td>
287 <td><span class="revision" title="Revision 104643"><a href="http://trac. webkit.org/changeset/104643">104643</a></span></td>
288 <td class="success">failure</td> <td><a href=".../37604">#37604</a></ td>
289 <td class="left">Build successful</td>
290 </tr>
291 <tr class="">
292 <td>Jan 10 15:32</td>
293 <td><span class="revision" title="Revision 104636"><a href="http://trac. webkit.org/changeset/104636">104636</a></span></td>
294 <td class="success">failure</td> <td><a href=".../37603">#37603</a></ td>
295 <td class="left">Build successful</td>
296 </tr>
297 <tr class="alt">
298 <td>Jan 10 15:18</td>
299 <td><span class="revision" title="Revision 104635"><a href="http://trac. webkit.org/changeset/104635">104635</a></span></td>
300 <td class="success">success</td> <td><a href=".../37602">#37602</a></ td>
301 <td class="left">Build successful</td>
302 </tr>
303 <tr class="">
304 <td>Jan 10 14:51</td>
305 <td><span class="revision" title="Revision 104633"><a href="http://trac. webkit.org/changeset/104633">104633</a></span></td>
306 <td class="failure">failure</td> <td><a href=".../37601">#37601</a></ td>
307 <td class="left">Failed compile-webkit</td>
308 </tr>
309 </table>
310 </body>'''
311 _fake_builder_page_without_success = '''
312 <body>
313 <table>
314 <tr class="alt">
315 <td>Jan 10 15:49</td>
316 <td><span class="revision" title="Revision 104643"><a href="http://trac. webkit.org/changeset/104643">104643</a></span></td>
317 <td class="success">failure</td>
318 </tr>
319 <tr class="">
320 <td>Jan 10 15:32</td>
321 <td><span class="revision" title="Revision 104636"><a href="http://trac. webkit.org/changeset/104636">104636</a></span></td>
322 <td class="success">failure</td>
323 </tr>
324 <tr class="alt">
325 <td>Jan 10 15:18</td>
326 <td><span class="revision" title="Revision 104635"><a href="http://trac. webkit.org/changeset/104635">104635</a></span></td>
327 <td class="success">failure</td>
328 </tr>
329 <tr class="">
330 <td>Jan 10 11:58</td>
331 <td><span class="revision" title="Revision ??"><a href="http://trac.we bkit.org/changeset/%3F%3F">??</a></span></td>
332 <td class="retry">retry</td>
333 </tr>
334 <tr class="">
335 <td>Jan 10 14:51</td>
336 <td><span class="revision" title="Revision 104633"><a href="http://trac. webkit.org/changeset/104633">104633</a></span></td>
337 <td class="failure">failure</td>
338 </tr>
339 </table>
340 </body>'''
341
342 def test_revisions_for_builder(self):
343 buildbot = BuildBot()
344 buildbot._fetch_builder_page = lambda builder: builder.page
345 builder_with_success = Builder('Some builder', None)
346 builder_with_success.page = self._fake_builder_page
347 self.assertEqual(
348 buildbot._revisions_for_builder(builder_with_success),
349 [(104643, False), (104636, False), (104635, True), (104633, False)])
350
351 builder_without_success = Builder('Some builder', None)
352 builder_without_success.page = self._fake_builder_page_without_success
353 self.assertEqual(
354 buildbot._revisions_for_builder(builder_without_success),
355 [(104643, False), (104636, False), (104635, False), (104633, False)] )
356
357 def test_find_green_revision(self):
358 buildbot = BuildBot()
359 self.assertEqual(buildbot._find_green_revision({
360 'Builder 1': [(1, True), (3, True)],
361 'Builder 2': [(1, True), (3, False)],
362 'Builder 3': [(1, True), (3, True)],
363 }), 1)
364 self.assertEqual(buildbot._find_green_revision({
365 'Builder 1': [(1, False), (3, True)],
366 'Builder 2': [(1, True), (3, True)],
367 'Builder 3': [(1, True), (3, True)],
368 }), 3)
369 self.assertEqual(buildbot._find_green_revision({
370 'Builder 1': [(1, True), (2, True)],
371 'Builder 2': [(1, False), (2, True), (3, True)],
372 'Builder 3': [(1, True), (3, True)],
373 }), None)
374 self.assertEqual(buildbot._find_green_revision({
375 'Builder 1': [(1, True), (2, True)],
376 'Builder 2': [(1, True), (2, True), (3, True)],
377 'Builder 3': [(1, True), (3, True)],
378 }), 2)
379 self.assertEqual(buildbot._find_green_revision({
380 'Builder 1': [(1, False), (2, True)],
381 'Builder 2': [(1, True), (3, True)],
382 'Builder 3': [(1, True), (3, True)],
383 }), None)
384 self.assertEqual(buildbot._find_green_revision({
385 'Builder 1': [(1, True), (3, True)],
386 'Builder 2': [(1, False), (2, True), (3, True), (4, True)],
387 'Builder 3': [(2, True), (4, True)],
388 }), 3)
389 self.assertEqual(buildbot._find_green_revision({
390 'Builder 1': [(1, True), (3, True)],
391 'Builder 2': [(1, False), (2, True), (3, True), (4, False)],
392 'Builder 3': [(2, True), (4, True)],
393 }), None)
394 self.assertEqual(buildbot._find_green_revision({
395 'Builder 1': [(1, True), (3, True)],
396 'Builder 2': [(1, False), (2, True), (3, True), (4, False)],
397 'Builder 3': [(2, True), (3, True), (4, True)],
398 }), 3)
399 self.assertEqual(buildbot._find_green_revision({
400 'Builder 1': [(1, True), (2, True)],
401 'Builder 2': [],
402 'Builder 3': [(1, True), (2, True)],
403 }), None)
404 self.assertEqual(buildbot._find_green_revision({
405 'Builder 1': [(1, True), (3, False), (5, True), (10, True), (12, Fal se)],
406 'Builder 2': [(1, True), (3, False), (7, True), (9, True), (12, Fals e)],
407 'Builder 3': [(1, True), (3, True), (7, True), (11, False), (12, Tru e)],
408 }), 7)
409
410 def _fetch_build(self, build_number):
411 if build_number == 5:
412 return "correct build"
413 return "wrong build"
414
415 def _fetch_revision_to_build_map(self):
416 return {'r5': 5, 'r2': 2, 'r3': 3}
417
418 def test_latest_cached_build(self):
419 b = Builder('builder', BuildBot())
420 b._fetch_build = self._fetch_build
421 b._fetch_revision_to_build_map = self._fetch_revision_to_build_map
422 self.assertEqual("correct build", b.latest_cached_build())
423
424 def results_url(self):
425 return "some-url"
426
427 def test_results_zip_url(self):
428 b = Build(None, 123, 123, False)
429 b.results_url = self.results_url
430 self.assertEqual("some-url.zip", b.results_zip_url())
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698