| OLD | NEW |
| 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 Loading... |
| 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()) | |
| OLD | NEW |