| OLD | NEW |
| (Empty) |
| 1 #!/usr/bin/env python | |
| 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| 3 # Use of this source code is governed by a BSD-style license that can be | |
| 4 # found in the LICENSE file. | |
| 5 | |
| 6 """Unit tests for verification/try_job_on_rietveld.py.""" | |
| 7 | |
| 8 import logging | |
| 9 import os | |
| 10 import random | |
| 11 import string | |
| 12 import sys | |
| 13 import time | |
| 14 import unittest | |
| 15 | |
| 16 ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) | |
| 17 sys.path.insert(0, os.path.join(ROOT_DIR, '..')) | |
| 18 | |
| 19 # In tests/ | |
| 20 import mocks | |
| 21 from mocks import BuildbotBuildStep | |
| 22 | |
| 23 # In root | |
| 24 from verification import base | |
| 25 from verification import try_job_steps | |
| 26 from verification import try_job_on_rietveld | |
| 27 | |
| 28 | |
| 29 # Some tests produce more output if verbose, so we need to | |
| 30 # track if we are in verbose mode or not. | |
| 31 VERBOSE = False | |
| 32 | |
| 33 | |
| 34 def _posted(builders): | |
| 35 return 'trigger_try_jobs(42, 23, \'CQ\', False, \'HEAD\', %s)' % str(builders) | |
| 36 | |
| 37 | |
| 38 def gen_job_pending(**kwargs): | |
| 39 value = { | |
| 40 '__persistent_type__': 'RietveldTryJobPending', | |
| 41 'builder': None, | |
| 42 'clobber': False, | |
| 43 'init_time': 1., | |
| 44 'requested_steps': [], | |
| 45 'revision': None, | |
| 46 'tries': 1, | |
| 47 } | |
| 48 assert all(arg in value for arg in kwargs) | |
| 49 value.update(kwargs) | |
| 50 return value | |
| 51 | |
| 52 | |
| 53 def gen_job(**kwargs): | |
| 54 value = { | |
| 55 '__persistent_type__': 'RietveldTryJob', | |
| 56 'build': None, | |
| 57 'builder': None, | |
| 58 'clobber': False, | |
| 59 'completed': False, | |
| 60 'init_time': 1., | |
| 61 'parent_key': None, | |
| 62 'requested_steps': [], | |
| 63 'revision': None, | |
| 64 'started': 1, | |
| 65 'steps_failed': [], | |
| 66 'steps_passed': [], | |
| 67 'tries': 1, | |
| 68 } | |
| 69 assert all(arg in value for arg in kwargs) | |
| 70 value.update(kwargs) | |
| 71 return value | |
| 72 | |
| 73 | |
| 74 def gen_jobs(**kwargs): | |
| 75 value = { | |
| 76 '__persistent_type__': 'RietveldTryJobs', | |
| 77 'error_message': None, | |
| 78 'irrelevant': [], | |
| 79 'pendings': [], | |
| 80 'skipped': False, | |
| 81 'step_verifiers': [], | |
| 82 'try_jobs': {}, | |
| 83 } | |
| 84 for arg in kwargs: | |
| 85 if arg not in value: | |
| 86 raise Exception('Invalid arg %s' % str(arg)) | |
| 87 | |
| 88 value.update(kwargs) | |
| 89 | |
| 90 # Convert all the verifiers to dicts (i.e. serialize them). | |
| 91 value['step_verifiers'] = [step.as_dict() for step in value['step_verifiers']] | |
| 92 | |
| 93 return value | |
| 94 | |
| 95 | |
| 96 class TryJobOnRietveldBase(mocks.TestCase): | |
| 97 # Base class for all test cases testing try_job_rietveld.py. | |
| 98 def setUp(self): | |
| 99 super(TryJobOnRietveldBase, self).setUp() | |
| 100 self.timestamp = [] | |
| 101 self.mock(time, 'time', self._time) | |
| 102 self.email = 'user1@example.com' | |
| 103 self.user = 'user1' | |
| 104 self.step_verifiers = [ | |
| 105 try_job_steps.TryJobSteps( | |
| 106 builder_name='linux', | |
| 107 steps=['test1', 'test2']), | |
| 108 try_job_steps.TryJobSteps( | |
| 109 builder_name='mac', | |
| 110 steps=['test1', 'test2']), | |
| 111 ] | |
| 112 | |
| 113 def tearDown(self): | |
| 114 try: | |
| 115 if not self.has_failed(): | |
| 116 self.assertEqual(0, len(self.timestamp)) | |
| 117 finally: | |
| 118 super(TryJobOnRietveldBase, self).tearDown() | |
| 119 | |
| 120 def _time(self): | |
| 121 self.assertTrue(self.timestamp) | |
| 122 return self.timestamp.pop(0) | |
| 123 | |
| 124 | |
| 125 class TryRunnerRietveldTest(TryJobOnRietveldBase): | |
| 126 # These test cases setup self.try_runner and call .verify() and | |
| 127 # .update_status() to test it. | |
| 128 def setUp(self): | |
| 129 super(TryRunnerRietveldTest, self).setUp() | |
| 130 self.try_runner = None | |
| 131 self._change_step_verifiers(self.step_verifiers) | |
| 132 | |
| 133 # Patch it a little. | |
| 134 self.buildbot_status = mocks.BuildbotMock(self) | |
| 135 self.mock( | |
| 136 try_job_on_rietveld.buildbot_json, | |
| 137 'Buildbot', | |
| 138 lambda _: self.buildbot_status) | |
| 139 | |
| 140 self.pending.revision = 123 | |
| 141 | |
| 142 # It's what rietveld is going to report. | |
| 143 self._key = (self.pending.issue, self.pending.patchset) | |
| 144 self.context.rietveld.patchsets_properties[self._key] = { | |
| 145 'try_job_results': [], | |
| 146 } | |
| 147 | |
| 148 def tearDown(self): | |
| 149 try: | |
| 150 if not self.has_failed(): | |
| 151 # Not to confuse with self.context.status which is AsyncPush mock. | |
| 152 self.buildbot_status.check_calls([]) | |
| 153 finally: | |
| 154 super(TryRunnerRietveldTest, self).tearDown() | |
| 155 | |
| 156 def _change_step_verifiers(self, step_verifiers): | |
| 157 """Change the current step verifiers and update any objects that used | |
| 158 the old ones.""" | |
| 159 self.step_verifiers = step_verifiers | |
| 160 | |
| 161 # time is requested in the object construction below and self.timestamp | |
| 162 # will be empty at the end of this function call. | |
| 163 self.timestamp.append(1.) | |
| 164 self.try_runner = try_job_on_rietveld.TryRunnerRietveld( | |
| 165 self.context, | |
| 166 'http://foo/bar', | |
| 167 self.email, | |
| 168 self.step_verifiers, | |
| 169 ['ignored_step'], | |
| 170 'sol', | |
| 171 ) | |
| 172 self.try_runner.update_latency = 0 | |
| 173 | |
| 174 | |
| 175 def _get_verif(self): | |
| 176 """Returns the RietveldTryJobs instance associated to this PendCommit.""" | |
| 177 return self.pending.verifications[self.try_runner.name] | |
| 178 | |
| 179 def _assert_pending_is_empty(self): | |
| 180 actual = self._get_verif().as_dict() | |
| 181 expected = gen_jobs( | |
| 182 step_verifiers=[ | |
| 183 try_job_steps.TryJobSteps( | |
| 184 builder_name='linux', | |
| 185 steps=['test1', 'test2']), | |
| 186 try_job_steps.TryJobSteps( | |
| 187 builder_name='mac', | |
| 188 steps=['test1', 'test2']), | |
| 189 ], | |
| 190 pendings=[ | |
| 191 gen_job_pending(builder=u'linux', requested_steps=['test1', 'test2']), | |
| 192 gen_job_pending(builder=u'mac', requested_steps=['test1', 'test2']), | |
| 193 ]) | |
| 194 self.assertEqual(expected, actual) | |
| 195 | |
| 196 def _add_build(self, builder, buildnumber, revision, steps, completed): | |
| 197 """Adds a build with a randomly generated key. | |
| 198 | |
| 199 Adds the build to both the try server and to Rietveld. | |
| 200 """ | |
| 201 key = ''.join(random.choice(string.ascii_letters) for _ in xrange(8)) | |
| 202 build = self.buildbot_status.add_build( | |
| 203 builder, buildnumber, revision, key, completed, None) | |
| 204 build.steps.extend(steps) | |
| 205 self.context.rietveld.patchsets_properties[self._key][ | |
| 206 'try_job_results'].append( | |
| 207 { | |
| 208 'key': key, | |
| 209 'builder': builder, | |
| 210 'buildnumber': buildnumber, | |
| 211 }) | |
| 212 return key | |
| 213 | |
| 214 def _add_triggered_build(self, builder, buildnumber, revision, steps, | |
| 215 completed, parent_key): | |
| 216 """Adds a triggered build with a randomly generated key. | |
| 217 | |
| 218 Adds the build to both the try server and to Rietveld. | |
| 219 """ | |
| 220 key = ''.join(random.choice(string.ascii_letters) for _ in xrange(8)) | |
| 221 build = self.buildbot_status.add_build( | |
| 222 builder, buildnumber, revision, key, completed, parent_key) | |
| 223 build.steps.extend(steps) | |
| 224 self.context.rietveld.patchsets_properties[self._key][ | |
| 225 'try_job_results'].append( | |
| 226 { | |
| 227 'key': key, | |
| 228 'builder': builder, | |
| 229 'buildnumber': buildnumber, | |
| 230 }) | |
| 231 return key | |
| 232 | |
| 233 def check_pending(self, num_status, rietveld, state, err): | |
| 234 self.context.status.check_names(['try job rietveld'] * num_status) | |
| 235 self.context.rietveld.check_calls(rietveld) | |
| 236 self.assertEqual(state, self.pending.get_state()) | |
| 237 self.assertEqual(err, self.pending.error_message()) | |
| 238 | |
| 239 def check_verif(self, need, waiting): | |
| 240 rietveld_try_jobs = self._get_verif() | |
| 241 self.assertEqual(need, rietveld_try_jobs.tests_need_to_be_run(1.)) | |
| 242 self.assertEqual(waiting, rietveld_try_jobs.tests_waiting_for_result()) | |
| 243 if not waiting: | |
| 244 why_not = None | |
| 245 else: | |
| 246 why_not = ( | |
| 247 'Waiting for the following jobs:\n' + | |
| 248 ''.join( | |
| 249 ' %s: %s\n' % (b, ','.join(waiting[b])) for b in sorted(waiting))) | |
| 250 self.assertEqual(why_not, rietveld_try_jobs.why_not()) | |
| 251 | |
| 252 def call_verify( | |
| 253 self, timestamps, num_status, rietveld, state, err, need, waiting): | |
| 254 """Calls TryRunnerRietveld.verify(). | |
| 255 | |
| 256 Makes sure the specified number of time.time() calls occurred. | |
| 257 """ | |
| 258 self.assertEqual(0, len(self.timestamp)) | |
| 259 self.timestamp = timestamps | |
| 260 self.try_runner.verify(self.pending) | |
| 261 self.assertEqual(0, len(self.timestamp)) | |
| 262 self.check_pending(num_status, rietveld, state, err) | |
| 263 self.check_verif(need, waiting) | |
| 264 | |
| 265 def call_update_status( | |
| 266 self, timestamps, num_status, rietveld, state, err, need, waiting): | |
| 267 """Calls TryRunnerRietveld.update_status(). | |
| 268 """ | |
| 269 self.timestamp = timestamps | |
| 270 self.try_runner.update_status([self.pending]) | |
| 271 self.check_pending(num_status, rietveld, state, err) | |
| 272 self.check_verif(need, waiting) | |
| 273 | |
| 274 def testVoid(self): | |
| 275 self.assertEqual(self.pending.verifications.keys(), []) | |
| 276 self.assertEqual(base.PROCESSING, self.pending.get_state()) | |
| 277 self.assertEqual('', self.pending.error_message()) | |
| 278 | |
| 279 def testVoidUpdate(self): | |
| 280 self.try_runner.update_status([]) | |
| 281 self.assertEqual(base.PROCESSING, self.pending.get_state()) | |
| 282 self.assertEqual('', self.pending.error_message()) | |
| 283 | |
| 284 def testVerificationVoid(self): | |
| 285 self.call_verify( | |
| 286 [1.] * 3, | |
| 287 num_status=2, | |
| 288 rietveld=[ | |
| 289 _posted({u"linux": ["test1", "test2"]}), | |
| 290 _posted({u"mac": ["test1", "test2"]}), | |
| 291 ], | |
| 292 state=base.PROCESSING, | |
| 293 err='', | |
| 294 need={}, | |
| 295 waiting={'linux': ['test1', 'test2'], 'mac': ['test1', 'test2']}) | |
| 296 self._assert_pending_is_empty() | |
| 297 | |
| 298 def testVerificationUpdateNoJob(self): | |
| 299 self.call_verify( | |
| 300 [1.] * 3, | |
| 301 num_status=2, | |
| 302 rietveld=[ | |
| 303 _posted({u"linux": ["test1", "test2"]}), | |
| 304 _posted({u"mac": ["test1", "test2"]}), | |
| 305 ], | |
| 306 state=base.PROCESSING, | |
| 307 err='', | |
| 308 need={}, | |
| 309 waiting={'linux': ['test1', 'test2'], 'mac': ['test1', 'test2']}) | |
| 310 self._assert_pending_is_empty() | |
| 311 self.call_update_status( | |
| 312 [1.] * 2, | |
| 313 num_status=0, | |
| 314 rietveld=[], | |
| 315 state=base.PROCESSING, | |
| 316 err='', | |
| 317 need={}, | |
| 318 waiting={'linux': ['test1', 'test2'], 'mac': ['test1', 'test2']}) | |
| 319 self._assert_pending_is_empty() | |
| 320 | |
| 321 def testVerificationUpdate(self): | |
| 322 self.call_verify( | |
| 323 [1.] * 3, | |
| 324 num_status=2, | |
| 325 rietveld=[ | |
| 326 _posted({u"linux": ["test1", "test2"]}), | |
| 327 _posted({u"mac": ["test1", "test2"]}), | |
| 328 ], | |
| 329 state=base.PROCESSING, | |
| 330 err='', | |
| 331 need={}, | |
| 332 waiting={'linux': ['test1', 'test2'], 'mac': ['test1', 'test2']}) | |
| 333 self._assert_pending_is_empty() | |
| 334 key = self._add_build('mac', 32, 42, [], False) | |
| 335 | |
| 336 self.call_update_status( | |
| 337 [1.] * (3 + 1 * VERBOSE), | |
| 338 num_status=1, | |
| 339 rietveld=[], | |
| 340 state=base.PROCESSING, | |
| 341 err='', | |
| 342 need={}, | |
| 343 waiting={'linux': ['test1', 'test2'], 'mac': ['test1', 'test2']}) | |
| 344 expected = gen_jobs( | |
| 345 step_verifiers=[ | |
| 346 try_job_steps.TryJobSteps( | |
| 347 builder_name='linux', | |
| 348 steps=['test1', 'test2']), | |
| 349 try_job_steps.TryJobSteps( | |
| 350 builder_name='mac', | |
| 351 steps=['test1', 'test2']), | |
| 352 ], | |
| 353 pendings=[ | |
| 354 gen_job_pending(builder='linux', requested_steps=['test1', 'test2']), | |
| 355 ], | |
| 356 try_jobs={ | |
| 357 key: gen_job( | |
| 358 builder='mac', | |
| 359 build=32, | |
| 360 requested_steps=['test1', 'test2'], | |
| 361 revision=42), | |
| 362 }) | |
| 363 self.assertEqual(expected, self._get_verif().as_dict()) | |
| 364 | |
| 365 def testVerificationSuccess(self): | |
| 366 self.call_verify( | |
| 367 [1.] * 3, | |
| 368 num_status=2, | |
| 369 rietveld=[ | |
| 370 _posted({u"linux": ["test1", "test2"]}), | |
| 371 _posted({u"mac": ["test1", "test2"]}), | |
| 372 ], | |
| 373 state=base.PROCESSING, | |
| 374 err='', | |
| 375 need={}, | |
| 376 waiting={'linux': ['test1', 'test2'], 'mac': ['test1', 'test2']}) | |
| 377 key1 = self._add_build( | |
| 378 'mac', 32, 42, | |
| 379 [BuildbotBuildStep('test1', True), BuildbotBuildStep('test2', True)], | |
| 380 False) | |
| 381 key2 = self._add_build( | |
| 382 'linux', 32, 42, | |
| 383 [BuildbotBuildStep('test1', True), BuildbotBuildStep('test2', True)], | |
| 384 False) | |
| 385 | |
| 386 self.call_update_status( | |
| 387 [1.] * (4 + 2 * VERBOSE), | |
| 388 num_status=2, | |
| 389 rietveld=[], | |
| 390 state=base.SUCCEEDED, | |
| 391 err='', | |
| 392 need={}, | |
| 393 waiting={}) | |
| 394 expected = gen_jobs( | |
| 395 step_verifiers=[ | |
| 396 try_job_steps.TryJobSteps( | |
| 397 builder_name='linux', | |
| 398 steps=['test1', 'test2']), | |
| 399 try_job_steps.TryJobSteps( | |
| 400 builder_name='mac', | |
| 401 steps=['test1', 'test2']), | |
| 402 ], | |
| 403 try_jobs={ | |
| 404 key1: gen_job( | |
| 405 builder=u'mac', | |
| 406 build=32, | |
| 407 requested_steps=['test1', 'test2'], | |
| 408 steps_passed=['test1', 'test2'], | |
| 409 revision=42), | |
| 410 key2: gen_job( | |
| 411 builder=u'linux', | |
| 412 build=32, | |
| 413 requested_steps=['test1', 'test2'], | |
| 414 steps_passed=['test1', 'test2'], | |
| 415 revision=42), | |
| 416 }) | |
| 417 self.assertEqual(expected, self._get_verif().as_dict()) | |
| 418 | |
| 419 def testVerificationRetrySuccess(self): | |
| 420 self.call_verify( | |
| 421 [1.] * 3, | |
| 422 num_status=2, | |
| 423 rietveld=[ | |
| 424 _posted({u"linux": ["test1", "test2"]}), | |
| 425 _posted({u"mac": ["test1", "test2"]}), | |
| 426 ], | |
| 427 state=base.PROCESSING, | |
| 428 err='', | |
| 429 need={}, | |
| 430 waiting={'linux': ['test1', 'test2'], 'mac': ['test1', 'test2']}) | |
| 431 key1 = self._add_build( | |
| 432 'mac', 32, 42, | |
| 433 [BuildbotBuildStep('test1', True), BuildbotBuildStep('test2', False)], | |
| 434 False) | |
| 435 key2 = self._add_build( | |
| 436 'linux', 32, 42, | |
| 437 [BuildbotBuildStep('test1', True), BuildbotBuildStep('test2', True)], | |
| 438 False) | |
| 439 | |
| 440 self.call_update_status( | |
| 441 [1.] * (5 + 2 * VERBOSE), | |
| 442 num_status=3, | |
| 443 rietveld=[_posted({u"mac": ["test2"]})], | |
| 444 state=base.PROCESSING, | |
| 445 err='', | |
| 446 need={}, | |
| 447 waiting={'mac': ['test2']}) | |
| 448 expected = gen_jobs( | |
| 449 step_verifiers=[ | |
| 450 try_job_steps.TryJobSteps( | |
| 451 builder_name='linux', | |
| 452 steps=['test1', 'test2']), | |
| 453 try_job_steps.TryJobSteps( | |
| 454 builder_name='mac', | |
| 455 steps=['test1', 'test2']), | |
| 456 ], | |
| 457 pendings=[ | |
| 458 gen_job_pending(builder=u'mac', requested_steps=['test2'], tries=2), | |
| 459 ], | |
| 460 try_jobs={ | |
| 461 key1: gen_job( | |
| 462 builder=u'mac', | |
| 463 build=32, | |
| 464 requested_steps=['test1', 'test2'], | |
| 465 steps_failed=['test2'], | |
| 466 steps_passed=['test1'], | |
| 467 revision=42), | |
| 468 key2: gen_job( | |
| 469 builder=u'linux', | |
| 470 build=32, | |
| 471 requested_steps=['test1', 'test2'], | |
| 472 steps_passed=['test1', 'test2'], | |
| 473 revision=42), | |
| 474 }) | |
| 475 self.assertEqual(expected, self._get_verif().as_dict()) | |
| 476 | |
| 477 # Add a new build on mac where test2 passed. | |
| 478 key3 = self._add_build( | |
| 479 'mac', 33, 42, | |
| 480 [BuildbotBuildStep('test1', False), BuildbotBuildStep('test2', True)], | |
| 481 False) | |
| 482 self.call_update_status( | |
| 483 [1.] * (5 + 1 * VERBOSE), | |
| 484 num_status=3, | |
| 485 rietveld=[], | |
| 486 state=base.SUCCEEDED, | |
| 487 err='', | |
| 488 need={}, | |
| 489 waiting={}) | |
| 490 expected = gen_jobs( | |
| 491 step_verifiers=[ | |
| 492 try_job_steps.TryJobSteps( | |
| 493 builder_name='linux', | |
| 494 steps=['test1', 'test2']), | |
| 495 try_job_steps.TryJobSteps( | |
| 496 builder_name='mac', | |
| 497 steps=['test1', 'test2']), | |
| 498 ], | |
| 499 try_jobs={ | |
| 500 key1: gen_job( | |
| 501 build=32, | |
| 502 builder='mac', | |
| 503 requested_steps=['test1', 'test2'], | |
| 504 steps_failed=['test2'], | |
| 505 steps_passed=['test1'], | |
| 506 revision=42), | |
| 507 key2: gen_job( | |
| 508 builder='linux', | |
| 509 build=32, | |
| 510 requested_steps=['test1', 'test2'], | |
| 511 revision=42, | |
| 512 steps_passed=['test1', 'test2']), | |
| 513 key3: gen_job( | |
| 514 builder='mac', | |
| 515 build=33, | |
| 516 requested_steps=['test2'], | |
| 517 revision=42, | |
| 518 steps_failed=['test1'], | |
| 519 steps_passed=['test2'], | |
| 520 tries=2), | |
| 521 }) | |
| 522 self.assertEqual(expected, self._get_verif().as_dict()) | |
| 523 | |
| 524 def testVerificationRetryRetry(self): | |
| 525 self.call_verify( | |
| 526 [1.] * 3, | |
| 527 num_status=2, | |
| 528 rietveld=[ | |
| 529 _posted({u"linux": ["test1", "test2"]}), | |
| 530 _posted({u"mac": ["test1", "test2"]}), | |
| 531 ], | |
| 532 state=base.PROCESSING, | |
| 533 err='', | |
| 534 need={}, | |
| 535 waiting={'linux': ['test1', 'test2'], 'mac': ['test1', 'test2']}) | |
| 536 key1 = self._add_build( | |
| 537 'mac', 32, 42, | |
| 538 [BuildbotBuildStep('test1', True), BuildbotBuildStep('test2', False)], | |
| 539 False) | |
| 540 key2 = self._add_build( | |
| 541 'linux', 32, 42, | |
| 542 [BuildbotBuildStep('test1', True), BuildbotBuildStep('test2', True)], | |
| 543 False) | |
| 544 | |
| 545 self.call_update_status( | |
| 546 [1.] * (5 + 2 * VERBOSE), | |
| 547 num_status=3, | |
| 548 rietveld=[_posted({u"mac": ["test2"]})], | |
| 549 state=base.PROCESSING, | |
| 550 err='', | |
| 551 need={}, | |
| 552 waiting={'mac': ['test2']}) | |
| 553 expected = gen_jobs( | |
| 554 step_verifiers=[ | |
| 555 try_job_steps.TryJobSteps( | |
| 556 builder_name='linux', | |
| 557 steps=['test1', 'test2']), | |
| 558 try_job_steps.TryJobSteps( | |
| 559 builder_name='mac', | |
| 560 steps=['test1', 'test2']), | |
| 561 ], | |
| 562 pendings=[ | |
| 563 gen_job_pending(builder='mac', requested_steps=['test2'], tries=2), | |
| 564 ], | |
| 565 try_jobs={ | |
| 566 key1: gen_job( | |
| 567 builder='mac', | |
| 568 build=32, | |
| 569 requested_steps=['test1', 'test2'], | |
| 570 steps_failed=['test2'], | |
| 571 steps_passed=['test1'], | |
| 572 revision=42), | |
| 573 key2: gen_job( | |
| 574 builder='linux', | |
| 575 build=32, | |
| 576 requested_steps=['test1', 'test2'], | |
| 577 steps_passed=['test1', 'test2'], | |
| 578 revision=42), | |
| 579 }) | |
| 580 self.assertEqual(expected, self._get_verif().as_dict()) | |
| 581 | |
| 582 # Add a new build on mac where test2 failed. | |
| 583 key3 = self._add_build('mac', 33, 42, [BuildbotBuildStep('test2', False)], | |
| 584 False) | |
| 585 | |
| 586 self.call_update_status( | |
| 587 [1.] * (6 + 1 * VERBOSE), | |
| 588 num_status=4, | |
| 589 rietveld=[_posted({u"mac": ["test2"]})], | |
| 590 state=base.PROCESSING, | |
| 591 err='', | |
| 592 need={}, | |
| 593 waiting={'mac': ['test2']}) | |
| 594 expected = gen_jobs( | |
| 595 step_verifiers=[ | |
| 596 try_job_steps.TryJobSteps( | |
| 597 builder_name='linux', | |
| 598 steps=['test1', 'test2']), | |
| 599 try_job_steps.TryJobSteps( | |
| 600 builder_name='mac', | |
| 601 steps=['test1', 'test2']), | |
| 602 ], | |
| 603 pendings=[ | |
| 604 gen_job_pending(builder='mac', requested_steps=['test2'], tries=3), | |
| 605 ], | |
| 606 try_jobs={ | |
| 607 key1: gen_job( | |
| 608 build=32, | |
| 609 builder='mac', | |
| 610 requested_steps=['test1', 'test2'], | |
| 611 steps_failed=['test2'], | |
| 612 steps_passed=['test1'], | |
| 613 revision=42), | |
| 614 key2: gen_job( | |
| 615 builder='linux', | |
| 616 build=32, | |
| 617 requested_steps=['test1', 'test2'], | |
| 618 revision=42, | |
| 619 steps_passed=['test1', 'test2']), | |
| 620 key3: gen_job( | |
| 621 builder='mac', | |
| 622 build=33, | |
| 623 requested_steps=['test2'], | |
| 624 revision=42, | |
| 625 steps_failed=['test2'], | |
| 626 tries=2), | |
| 627 }) | |
| 628 self.assertEqual(expected, self._get_verif().as_dict()) | |
| 629 | |
| 630 # Add a new build on mac where test2 failed again! Too bad now. | |
| 631 self._add_build('mac', 34, 42, [BuildbotBuildStep('test2', False)], False) | |
| 632 | |
| 633 self.call_update_status( | |
| 634 [1.] * (6 + 2 * VERBOSE), | |
| 635 num_status=4, | |
| 636 rietveld=[], | |
| 637 state=base.FAILED, | |
| 638 err=( | |
| 639 u'Retried try job too often on mac for step(s) test2\n' | |
| 640 'http://foo/bar/buildstatus?builder=mac&number=34'), | |
| 641 need={}, | |
| 642 waiting={}) | |
| 643 | |
| 644 def testVerificationRetryRetryTriggered(self): | |
| 645 step_verifiers = [ | |
| 646 try_job_steps.TryJobTriggeredSteps( | |
| 647 builder_name='triggered', | |
| 648 trigger_name='builder', | |
| 649 steps={'test1': 'build'})] | |
| 650 self._change_step_verifiers(step_verifiers) | |
| 651 | |
| 652 self.call_verify( | |
| 653 [1.] * 3, | |
| 654 num_status=2, | |
| 655 rietveld=[ | |
| 656 _posted({u"builder": ["build"]}), | |
| 657 ], | |
| 658 state=base.PROCESSING, | |
| 659 err='', | |
| 660 need={}, | |
| 661 waiting={'triggered': ['test1']}) | |
| 662 | |
| 663 # The trigger bot passed, but the triggered bot fails. | |
| 664 key1 = self._add_build('builder', 1, 42, [BuildbotBuildStep('build', True)], | |
| 665 True) | |
| 666 self._add_triggered_build('triggered', 1, 42, | |
| 667 [BuildbotBuildStep('test1', False)], True, key1) | |
| 668 triggered_key_1 = 'triggered/1_triggered_%s' % key1 | |
| 669 | |
| 670 self.call_update_status( | |
| 671 [1.] * (6 + 2 * VERBOSE), | |
| 672 num_status=4, | |
| 673 rietveld=[_posted({u"builder": ["build"]})], | |
| 674 state=base.PROCESSING, | |
| 675 err='', | |
| 676 need={}, | |
| 677 waiting={'triggered': ['test1']}) | |
| 678 expected = gen_jobs( | |
| 679 step_verifiers=[ | |
| 680 try_job_steps.TryJobTriggeredSteps( | |
| 681 builder_name='triggered', | |
| 682 trigger_name='builder', | |
| 683 steps={'test1': 'build'})], | |
| 684 pendings=[ | |
| 685 gen_job_pending(builder='builder', requested_steps=['build'], tries=2), | |
| 686 gen_job_pending(builder='triggered', requested_steps=['test1'], | |
| 687 tries=2), | |
| 688 ], | |
| 689 try_jobs={ | |
| 690 key1: gen_job( | |
| 691 builder='builder', | |
| 692 build=1, | |
| 693 requested_steps=['build'], | |
| 694 steps_passed=['build'], | |
| 695 completed=True, | |
| 696 revision=42, | |
| 697 tries=1, | |
| 698 ), | |
| 699 triggered_key_1: gen_job( | |
| 700 builder='triggered', | |
| 701 build=1, | |
| 702 requested_steps=['test1'], | |
| 703 steps_failed=['test1'], | |
| 704 completed=True, | |
| 705 revision=42, | |
| 706 parent_key=key1, | |
| 707 tries=1, | |
| 708 ), | |
| 709 }) | |
| 710 self.assertEqual(expected, self._get_verif().as_dict()) | |
| 711 | |
| 712 # Triggered bot fails again. | |
| 713 key2 = self._add_build('builder', 2, 42, [BuildbotBuildStep('build', True)], | |
| 714 True) | |
| 715 self._add_triggered_build('triggered', 2, 42, | |
| 716 [BuildbotBuildStep('test1', False)], True, key2) | |
| 717 triggered_key_2 = 'triggered/2_triggered_%s' % key2 | |
| 718 | |
| 719 self.call_update_status( | |
| 720 [1.] * (6 + 2 * VERBOSE), | |
| 721 num_status=4, | |
| 722 rietveld=[_posted({u"builder": ["build"]})], | |
| 723 state=base.PROCESSING, | |
| 724 err='', | |
| 725 need={}, | |
| 726 waiting={'triggered': ['test1']}) | |
| 727 expected = gen_jobs( | |
| 728 step_verifiers=[ | |
| 729 try_job_steps.TryJobTriggeredSteps( | |
| 730 builder_name='triggered', | |
| 731 trigger_name='builder', | |
| 732 steps={'test1': 'build'})], | |
| 733 pendings=[ | |
| 734 gen_job_pending(builder='builder', requested_steps=['build'], tries=3), | |
| 735 gen_job_pending(builder='triggered', requested_steps=['test1'], | |
| 736 tries=3), | |
| 737 ], | |
| 738 try_jobs={ | |
| 739 key1: gen_job( | |
| 740 builder='builder', | |
| 741 build=1, | |
| 742 requested_steps=['build'], | |
| 743 steps_passed=['build'], | |
| 744 completed=True, | |
| 745 revision=42, | |
| 746 tries=1, | |
| 747 ), | |
| 748 triggered_key_1: gen_job( | |
| 749 builder='triggered', | |
| 750 build=1, | |
| 751 requested_steps=['test1'], | |
| 752 steps_failed=['test1'], | |
| 753 completed=True, | |
| 754 revision=42, | |
| 755 parent_key=key1, | |
| 756 tries=1, | |
| 757 ), | |
| 758 key2: gen_job( | |
| 759 builder='builder', | |
| 760 build=2, | |
| 761 requested_steps=['build'], | |
| 762 steps_passed=['build'], | |
| 763 completed=True, | |
| 764 revision=42, | |
| 765 tries=2, | |
| 766 ), | |
| 767 triggered_key_2: gen_job( | |
| 768 builder='triggered', | |
| 769 build=2, | |
| 770 requested_steps=['test1'], | |
| 771 steps_failed=['test1'], | |
| 772 completed=True, | |
| 773 revision=42, | |
| 774 parent_key=key2, | |
| 775 tries=2, | |
| 776 ), | |
| 777 }) | |
| 778 self.assertEqual(expected, self._get_verif().as_dict()) | |
| 779 | |
| 780 # Triggered bot fails for the 3rd time, abort. | |
| 781 key3 = self._add_build('builder', 3, 1, [BuildbotBuildStep('build', True)], | |
| 782 True) | |
| 783 self._add_triggered_build('triggered', 3, 1, | |
| 784 [BuildbotBuildStep('test1', False)], True, key3) | |
| 785 self.call_update_status( | |
| 786 [1.] * (4 + 3 * VERBOSE), | |
| 787 num_status=2, | |
| 788 rietveld=[], | |
| 789 state=base.FAILED, | |
| 790 # TODO(csharp): Its the triggered bot that keeps failing, so that should | |
| 791 # be the bot mentioned here. | |
| 792 err=( | |
| 793 u'Retried try job too often on builder for step(s) build\n' | |
| 794 'http://foo/bar/buildstatus?builder=builder&number=3'), | |
| 795 need={}, | |
| 796 waiting={}) | |
| 797 | |
| 798 def testVerificationPreviousJobGood(self): | |
| 799 # Reuse the previous job if good. | |
| 800 key1 = self._add_build( | |
| 801 'mac', 32, 42, | |
| 802 [BuildbotBuildStep('test1', True), BuildbotBuildStep('test2', True)], | |
| 803 False) | |
| 804 | |
| 805 self.call_verify( | |
| 806 [1.] * (2 + 1 * VERBOSE), | |
| 807 num_status=1, | |
| 808 rietveld=[_posted({u"linux": ["test1", "test2"]})], | |
| 809 state=base.PROCESSING, | |
| 810 err='', | |
| 811 need={}, | |
| 812 waiting={'linux': ['test1', 'test2']}) | |
| 813 | |
| 814 # Sends an update to note the job was started. | |
| 815 self.call_update_status( | |
| 816 [1.] * 3, | |
| 817 num_status=1, | |
| 818 rietveld=[], | |
| 819 state=base.PROCESSING, | |
| 820 err='', | |
| 821 need={}, | |
| 822 waiting={'linux': ['test1', 'test2']}) | |
| 823 expected = gen_jobs( | |
| 824 step_verifiers=[ | |
| 825 try_job_steps.TryJobSteps( | |
| 826 builder_name='linux', | |
| 827 steps=['test1', 'test2']), | |
| 828 try_job_steps.TryJobSteps( | |
| 829 builder_name='mac', | |
| 830 steps=['test1', 'test2']), | |
| 831 ], | |
| 832 pendings=[ | |
| 833 gen_job_pending(builder='linux', requested_steps=['test1', 'test2']), | |
| 834 ], | |
| 835 try_jobs={ | |
| 836 key1: gen_job( | |
| 837 build=32, | |
| 838 builder='mac', | |
| 839 # Note that requested_steps is empty since testfilter is not parsed. | |
| 840 steps_passed=['test1', 'test2'], | |
| 841 revision=42, | |
| 842 # tries == 0 since we didn't start it. | |
| 843 tries=0), | |
| 844 }) | |
| 845 self.assertEqual(expected, self._get_verif().as_dict()) | |
| 846 | |
| 847 def _expired(self, now, **kwargs): | |
| 848 # Exacly like testVerificationPreviousJobGood except that jobs are always | |
| 849 # too old, either by revision or by timestamp. | |
| 850 key1 = self._add_build( | |
| 851 'mac', 32, 42, | |
| 852 [BuildbotBuildStep('test1', True), BuildbotBuildStep('test2', True)], | |
| 853 False) | |
| 854 | |
| 855 self.call_verify( | |
| 856 [now] * 3, | |
| 857 num_status=2, | |
| 858 rietveld=[ | |
| 859 _posted({u"linux": ["test1", "test2"]}), | |
| 860 _posted({u"mac": ["test1", "test2"]}), | |
| 861 ], | |
| 862 state=base.PROCESSING, | |
| 863 err='', | |
| 864 need={}, | |
| 865 waiting={'linux': ['test1', 'test2'], 'mac': ['test1', 'test2']}) | |
| 866 | |
| 867 self.call_update_status( | |
| 868 [now] * 2, | |
| 869 num_status=0, | |
| 870 rietveld=[], | |
| 871 state=base.PROCESSING, | |
| 872 err='', | |
| 873 need={}, | |
| 874 waiting={'linux': ['test1', 'test2'], 'mac': ['test1', 'test2']}) | |
| 875 expected = gen_jobs( | |
| 876 step_verifiers=[ | |
| 877 try_job_steps.TryJobSteps( | |
| 878 builder_name='linux', | |
| 879 steps=['test1', 'test2']), | |
| 880 try_job_steps.TryJobSteps( | |
| 881 builder_name='mac', | |
| 882 steps=['test1', 'test2']), | |
| 883 ], | |
| 884 irrelevant=[key1], | |
| 885 pendings=[ | |
| 886 gen_job_pending( | |
| 887 builder='linux', requested_steps=['test1', 'test2'], **kwargs), | |
| 888 gen_job_pending( | |
| 889 builder='mac', requested_steps=['test1', 'test2'], **kwargs), | |
| 890 ]) | |
| 891 self.assertEqual(expected, self._get_verif().as_dict()) | |
| 892 | |
| 893 def testVerificationPreviousExpiredRevisionTooOld(self): | |
| 894 self.context.checkout.revisions = lambda _r1, _r2: 201 | |
| 895 self._expired(1.) | |
| 896 | |
| 897 def testVerificationPreviousExpiredDateTooOld(self): | |
| 898 # 5 days old. | |
| 899 old = 5*24*60*60. | |
| 900 self._expired(old, init_time=old) | |
| 901 | |
| 902 def _previous_job_partially_good( | |
| 903 self, steps, steps_failed, completed, expect_mac_retry, num_time_verify, | |
| 904 num_time_update, num_status_update): | |
| 905 # Reuse the previous job tests that passed. | |
| 906 key1 = self._add_build('mac', 32, 42, steps, completed) | |
| 907 | |
| 908 expected_calls = [_posted({u"linux": ["test1", "test2"]})] | |
| 909 pendings = [ | |
| 910 gen_job_pending(builder='linux', requested_steps=['test1', 'test2']) | |
| 911 ] | |
| 912 if expect_mac_retry: | |
| 913 # No need to run test2 again. | |
| 914 expected_calls.append(_posted({u"mac": ["test1"]})) | |
| 915 pendings.append(gen_job_pending(builder='mac', requested_steps=['test1'])) | |
| 916 self.call_verify( | |
| 917 [1.] * (num_time_verify + 1 * VERBOSE), | |
| 918 num_status=len(expected_calls), | |
| 919 rietveld=expected_calls, | |
| 920 state=base.PROCESSING, | |
| 921 err='', | |
| 922 need={}, | |
| 923 waiting={'linux': ['test1', 'test2'], 'mac': ['test1']}) | |
| 924 self.call_update_status( | |
| 925 [1.] * num_time_update, | |
| 926 num_status=num_status_update, | |
| 927 rietveld=[], | |
| 928 state=base.PROCESSING, | |
| 929 err='', | |
| 930 need={}, | |
| 931 waiting={'linux': ['test1', 'test2'], 'mac': ['test1']}) | |
| 932 expected = gen_jobs( | |
| 933 step_verifiers=[ | |
| 934 try_job_steps.TryJobSteps( | |
| 935 builder_name='linux', | |
| 936 steps=['test1', 'test2']), | |
| 937 try_job_steps.TryJobSteps( | |
| 938 builder_name='mac', | |
| 939 steps=['test1', 'test2']), | |
| 940 ], | |
| 941 pendings=pendings, | |
| 942 try_jobs={ | |
| 943 key1: gen_job( | |
| 944 build=32, | |
| 945 builder='mac', | |
| 946 # Note that requested_steps is empty since testfilter is not parsed. | |
| 947 steps_failed=steps_failed, | |
| 948 steps_passed=['test2'], | |
| 949 revision=42, | |
| 950 # tries == 0 since we didn't start it. | |
| 951 tries=0, | |
| 952 completed=completed), | |
| 953 }) | |
| 954 self.assertEqual(expected, self._get_verif().as_dict()) | |
| 955 | |
| 956 def testVerificationPreviousJobPartiallyGood1(self): | |
| 957 # Only test1 will be run on mac since test2 had passed. | |
| 958 self._previous_job_partially_good( | |
| 959 [BuildbotBuildStep('test1', False), BuildbotBuildStep('test2', True)], | |
| 960 ['test1'], True, True, 3, 2, 0) | |
| 961 | |
| 962 def testVerificationPreviousJobPartiallyGood2(self): | |
| 963 # Let's assume a testfilter was used and test1 wasn't run. Only test1 will | |
| 964 # be run on mac. | |
| 965 self._previous_job_partially_good( | |
| 966 [BuildbotBuildStep('test2', True)], [], True, True, 3, 2, 0) | |
| 967 | |
| 968 def testVerificationPreviousJobPartiallyGood3(self): | |
| 969 # Test that we do not retry on mac until it completes. This is because | |
| 970 # CQ does not parse the test filter, so we do not know if the mac job | |
| 971 # will run test1. | |
| 972 # It's kind of weird, because it sends a status report like if it had | |
| 973 # started this job. | |
| 974 self._previous_job_partially_good( | |
| 975 [BuildbotBuildStep('test2', True)], [], False, False, 2, 3, 1) | |
| 976 | |
| 977 def testVerificationPreviousJobsWereGood(self): | |
| 978 # Reuse the previous jobs tests that passed. Do not send any try job. | |
| 979 key1 = self._add_build( | |
| 980 'mac', 32, 42, | |
| 981 [BuildbotBuildStep('test1', True), BuildbotBuildStep('test2', True)], | |
| 982 False) | |
| 983 key2 = self._add_build( | |
| 984 'linux', 32, 42, | |
| 985 [BuildbotBuildStep('test1', True), BuildbotBuildStep('test2', True)], | |
| 986 False) | |
| 987 | |
| 988 # People will love that! | |
| 989 self.call_verify( | |
| 990 [1.] * (1 + 2 * VERBOSE), | |
| 991 num_status=0, | |
| 992 rietveld=[], | |
| 993 state=base.SUCCEEDED, | |
| 994 err='', | |
| 995 need={}, | |
| 996 waiting={}) | |
| 997 | |
| 998 self.call_update_status( | |
| 999 [1.], | |
| 1000 num_status=0, | |
| 1001 rietveld=[], | |
| 1002 state=base.SUCCEEDED, | |
| 1003 err='', | |
| 1004 need={}, | |
| 1005 waiting={}) | |
| 1006 expected = gen_jobs( | |
| 1007 step_verifiers=[ | |
| 1008 try_job_steps.TryJobSteps( | |
| 1009 builder_name='linux', | |
| 1010 steps=['test1', 'test2']), | |
| 1011 try_job_steps.TryJobSteps( | |
| 1012 builder_name='mac', | |
| 1013 steps=['test1', 'test2']), | |
| 1014 ], | |
| 1015 try_jobs={ | |
| 1016 key1: gen_job( | |
| 1017 build=32, | |
| 1018 builder='mac', | |
| 1019 # Note that requested_steps is empty since testfilter is not parsed. | |
| 1020 steps_passed=['test1', 'test2'], | |
| 1021 revision=42, | |
| 1022 # tries == 0 since we didn't start it. | |
| 1023 tries=0), | |
| 1024 key2: gen_job( | |
| 1025 build=32, | |
| 1026 builder='linux', | |
| 1027 # Note that requested_steps is empty since testfilter is not parsed. | |
| 1028 steps_passed=['test1', 'test2'], | |
| 1029 revision=42, | |
| 1030 # tries == 0 since we didn't start it. | |
| 1031 tries=0), | |
| 1032 }) | |
| 1033 self.assertEqual(expected, self._get_verif().as_dict()) | |
| 1034 | |
| 1035 def testRietveldTryJobsPendingWasLost(self): | |
| 1036 # Requested a pending try job but the request was lost. | |
| 1037 self.try_runner.step_verifiers = [ | |
| 1038 try_job_steps.TryJobSteps( | |
| 1039 builder_name='linux', | |
| 1040 steps=['test1']), | |
| 1041 ] | |
| 1042 self.call_verify( | |
| 1043 [1.] * 2, | |
| 1044 num_status=1, | |
| 1045 rietveld=[_posted({u"linux": ["test1"]})], | |
| 1046 state=base.PROCESSING, | |
| 1047 err='', | |
| 1048 need={}, | |
| 1049 waiting={'linux': ['test1']}) | |
| 1050 self.call_update_status( | |
| 1051 [1.] * 2, | |
| 1052 num_status=0, | |
| 1053 rietveld=[], | |
| 1054 state=base.PROCESSING, | |
| 1055 err='', | |
| 1056 need={}, | |
| 1057 waiting={'linux': ['test1']}) | |
| 1058 | |
| 1059 # 3 minutes later | |
| 1060 later = 3. * 60 | |
| 1061 self.call_update_status( | |
| 1062 [later] * 2, | |
| 1063 num_status=0, | |
| 1064 rietveld=[], | |
| 1065 state=base.PROCESSING, | |
| 1066 err='', | |
| 1067 need={}, | |
| 1068 waiting={'linux': ['test1']}) | |
| 1069 expected = gen_jobs( | |
| 1070 step_verifiers=[ | |
| 1071 try_job_steps.TryJobSteps( | |
| 1072 builder_name='linux', | |
| 1073 steps=['test1']), | |
| 1074 ], | |
| 1075 pendings=[ | |
| 1076 gen_job_pending(builder=u'linux', requested_steps=['test1']), | |
| 1077 ]) | |
| 1078 | |
| 1079 # 1h later. | |
| 1080 later = 60. * 60 | |
| 1081 self.call_update_status( | |
| 1082 [later] * (2 + 1 * VERBOSE), | |
| 1083 num_status=0, | |
| 1084 rietveld=[], | |
| 1085 state=base.PROCESSING, | |
| 1086 err='', | |
| 1087 need={}, | |
| 1088 waiting={'linux': ['test1']}) | |
| 1089 expected = gen_jobs( | |
| 1090 step_verifiers=[ | |
| 1091 try_job_steps.TryJobSteps( | |
| 1092 builder_name='linux', | |
| 1093 steps=['test1']), | |
| 1094 ], | |
| 1095 pendings=[ | |
| 1096 gen_job_pending(builder=u'linux', requested_steps=['test1']), | |
| 1097 ]) | |
| 1098 self.assertEqual(expected, self._get_verif().as_dict()) | |
| 1099 | |
| 1100 def testRietveldTryJobsPendingTookSomeTime(self): | |
| 1101 # Requested a pending try job but the request took some time to propagate. | |
| 1102 self.try_runner.step_verifiers = [ | |
| 1103 try_job_steps.TryJobSteps( | |
| 1104 builder_name='linux', | |
| 1105 steps=['test1']), | |
| 1106 ] | |
| 1107 self.call_verify( | |
| 1108 [1.] * 2, | |
| 1109 num_status=1, | |
| 1110 rietveld=[_posted({u"linux": ["test1"]})], | |
| 1111 state=base.PROCESSING, | |
| 1112 err='', | |
| 1113 need={}, | |
| 1114 waiting={'linux': ['test1']}) | |
| 1115 self.call_update_status( | |
| 1116 [1.] * 2, | |
| 1117 num_status=0, | |
| 1118 rietveld=[], | |
| 1119 state=base.PROCESSING, | |
| 1120 err='', | |
| 1121 need={}, | |
| 1122 waiting={'linux': ['test1']}) | |
| 1123 # 3 minutes later | |
| 1124 later = 3. * 60 | |
| 1125 self.call_update_status( | |
| 1126 [later] * 2, | |
| 1127 num_status=0, | |
| 1128 rietveld=[], | |
| 1129 state=base.PROCESSING, | |
| 1130 err='', | |
| 1131 need={}, | |
| 1132 waiting={'linux': ['test1']}) | |
| 1133 expected = gen_jobs( | |
| 1134 step_verifiers=[ | |
| 1135 try_job_steps.TryJobSteps( | |
| 1136 builder_name='linux', | |
| 1137 steps=['test1']), | |
| 1138 ], | |
| 1139 pendings=[ | |
| 1140 gen_job_pending(builder=u'linux', requested_steps=['test1']), | |
| 1141 ]) | |
| 1142 self.assertEqual(expected, self._get_verif().as_dict()) | |
| 1143 | |
| 1144 # Queue it. | |
| 1145 self.buildbot_status.builders['linux'].pending_builds.data = [ | |
| 1146 { | |
| 1147 "builderName":"linux", | |
| 1148 "builds":[], | |
| 1149 "reason":"%d-1: None" % self.pending.issue, | |
| 1150 "source": { | |
| 1151 "changes": [ | |
| 1152 { | |
| 1153 "at": "Wed 05 Dec 2012 19:11:19", | |
| 1154 "files": [], | |
| 1155 "number": 268857, | |
| 1156 "project": "", | |
| 1157 "properties": [], | |
| 1158 "rev": "171358", | |
| 1159 "revision": "171358", | |
| 1160 "when": 1354763479, | |
| 1161 "who": self.pending.owner, | |
| 1162 }, | |
| 1163 ], | |
| 1164 "hasPatch": False, | |
| 1165 "project": "chrome", | |
| 1166 "repository": "", | |
| 1167 "revision": "171358", | |
| 1168 }, | |
| 1169 "submittedAt": 1354763479, | |
| 1170 }, | |
| 1171 ] | |
| 1172 | |
| 1173 # 1h later, it must not have queued another job. | |
| 1174 later = 60. * 60 | |
| 1175 self.call_update_status( | |
| 1176 [later] * 2, | |
| 1177 num_status=0, | |
| 1178 rietveld=[], | |
| 1179 state=base.PROCESSING, | |
| 1180 err='', | |
| 1181 need={}, | |
| 1182 waiting={'linux': ['test1']}) | |
| 1183 expected = gen_jobs( | |
| 1184 step_verifiers=[ | |
| 1185 try_job_steps.TryJobSteps( | |
| 1186 builder_name='linux', | |
| 1187 steps=['test1']), | |
| 1188 ], | |
| 1189 pendings=[ | |
| 1190 gen_job_pending( | |
| 1191 builder=u'linux', requested_steps=['test1']), | |
| 1192 ]) | |
| 1193 self.assertEqual(expected, self._get_verif().as_dict()) | |
| 1194 | |
| 1195 def testRietveldHung(self): | |
| 1196 # Send a try job and have it never start. | |
| 1197 self.try_runner.step_verifiers = [ | |
| 1198 try_job_steps.TryJobSteps( | |
| 1199 builder_name='linux', | |
| 1200 steps=['test1']), | |
| 1201 ] | |
| 1202 self.call_verify( | |
| 1203 [1.] * 2, | |
| 1204 num_status=1, | |
| 1205 rietveld=[_posted({u"linux": ["test1"]})], | |
| 1206 state=base.PROCESSING, | |
| 1207 err='', | |
| 1208 need={}, | |
| 1209 waiting={'linux': ['test1']}) | |
| 1210 key1 = self._add_build( | |
| 1211 'linux', 32, 42, | |
| 1212 [], | |
| 1213 False) | |
| 1214 self.call_update_status( | |
| 1215 [1.] * (3 + 1 * VERBOSE), | |
| 1216 num_status=1, | |
| 1217 rietveld=[], | |
| 1218 state=base.PROCESSING, | |
| 1219 err='', | |
| 1220 need={}, | |
| 1221 waiting={'linux': ['test1']}) | |
| 1222 | |
| 1223 expected = gen_jobs( | |
| 1224 step_verifiers=[ | |
| 1225 try_job_steps.TryJobSteps( | |
| 1226 builder_name='linux', | |
| 1227 steps=['test1']), | |
| 1228 ], | |
| 1229 try_jobs={ | |
| 1230 key1: gen_job( | |
| 1231 builder=u'linux', | |
| 1232 build=32, | |
| 1233 requested_steps=['test1'], | |
| 1234 steps_passed=[], | |
| 1235 revision=42, | |
| 1236 completed=False), | |
| 1237 }) | |
| 1238 | |
| 1239 self.assertEqual(expected, self._get_verif().as_dict()) | |
| 1240 | |
| 1241 # Fast forward in time to make the try job request "timeout". Basically, | |
| 1242 # the Try Job trigger on Rietveld was somehow ignored by the Try Server | |
| 1243 # itself. Test our chance by sending another trigger. | |
| 1244 later = 40. * 24 * 60 * 60 | |
| 1245 # Update the internal status. | |
| 1246 self.call_update_status( | |
| 1247 [later] * 3, | |
| 1248 num_status=1, | |
| 1249 rietveld=[_posted({u"linux": ["test1"]})], | |
| 1250 state=base.PROCESSING, | |
| 1251 err='', | |
| 1252 need={}, | |
| 1253 waiting={'linux': ['test1']}) | |
| 1254 | |
| 1255 self.assertEqual( | |
| 1256 'Waiting for the following jobs:\n linux: test1\n', | |
| 1257 self._get_verif().why_not()) | |
| 1258 | |
| 1259 expected_timed_out = gen_jobs( | |
| 1260 step_verifiers=[ | |
| 1261 try_job_steps.TryJobSteps( | |
| 1262 builder_name='linux', | |
| 1263 steps=['test1']), | |
| 1264 ], | |
| 1265 irrelevant=[key1], | |
| 1266 pendings=[ | |
| 1267 gen_job_pending( | |
| 1268 builder=u'linux', init_time=later, requested_steps=['test1']), | |
| 1269 ]) | |
| 1270 self.assertEqual(expected_timed_out, self._get_verif().as_dict()) | |
| 1271 | |
| 1272 def testVerificationBrokenTestOnHead(self): | |
| 1273 # The CQ retries until it aborts because the test is broken at HEAD on | |
| 1274 # mac/test2. | |
| 1275 self.call_verify( | |
| 1276 [1.] * 3, | |
| 1277 num_status=2, | |
| 1278 rietveld=[ | |
| 1279 _posted({u"linux": ["test1", "test2"]}), | |
| 1280 _posted({u"mac": ["test1", "test2"]}), | |
| 1281 ], | |
| 1282 state=base.PROCESSING, | |
| 1283 err='', | |
| 1284 need={}, | |
| 1285 waiting={'linux': ['test1', 'test2'], 'mac': ['test1', 'test2']}) | |
| 1286 key1 = self._add_build( | |
| 1287 'mac', 32, 42, | |
| 1288 [BuildbotBuildStep('test1', True), BuildbotBuildStep('test2', False)], | |
| 1289 True) | |
| 1290 key2 = self._add_build( | |
| 1291 'linux', 12, 22, | |
| 1292 [BuildbotBuildStep('test1', True), BuildbotBuildStep('test2', True)], | |
| 1293 True) | |
| 1294 | |
| 1295 self.call_update_status( | |
| 1296 [1.] * (5 + 2 * VERBOSE), | |
| 1297 num_status=3, | |
| 1298 rietveld=[_posted({u"mac": ["test2"]})], | |
| 1299 state=base.PROCESSING, | |
| 1300 err='', | |
| 1301 need={}, | |
| 1302 waiting={'mac': ['test2']}) | |
| 1303 expected = gen_jobs( | |
| 1304 step_verifiers=[ | |
| 1305 try_job_steps.TryJobSteps( | |
| 1306 builder_name='linux', | |
| 1307 steps=['test1', 'test2']), | |
| 1308 try_job_steps.TryJobSteps( | |
| 1309 builder_name='mac', | |
| 1310 steps=['test1', 'test2']), | |
| 1311 ], | |
| 1312 pendings=[ | |
| 1313 gen_job_pending(builder=u'mac', requested_steps=['test2'], tries=2), | |
| 1314 ], | |
| 1315 try_jobs={ | |
| 1316 key1: gen_job( | |
| 1317 builder=u'mac', | |
| 1318 build=32, | |
| 1319 completed=True, | |
| 1320 requested_steps=['test1', 'test2'], | |
| 1321 steps_failed=['test2'], | |
| 1322 steps_passed=['test1'], | |
| 1323 revision=42), | |
| 1324 key2: gen_job( | |
| 1325 builder=u'linux', | |
| 1326 build=12, | |
| 1327 completed=True, | |
| 1328 requested_steps=['test1', 'test2'], | |
| 1329 steps_passed=['test1', 'test2'], | |
| 1330 revision=22), | |
| 1331 }) | |
| 1332 self.assertEqual(expected, self._get_verif().as_dict()) | |
| 1333 | |
| 1334 key3 = self._add_build( | |
| 1335 'mac', 33, 42, | |
| 1336 [BuildbotBuildStep('test2', False)], | |
| 1337 True) | |
| 1338 self.call_update_status( | |
| 1339 [1.] * (4 + 1 * VERBOSE), | |
| 1340 num_status=2, | |
| 1341 rietveld=[_posted({u"mac": ["test2"]})], | |
| 1342 state=base.PROCESSING, | |
| 1343 err='', | |
| 1344 need={}, | |
| 1345 waiting={'mac': ['test2']}) | |
| 1346 expected = gen_jobs( | |
| 1347 step_verifiers=[ | |
| 1348 try_job_steps.TryJobSteps( | |
| 1349 builder_name='linux', | |
| 1350 steps=['test1', 'test2']), | |
| 1351 try_job_steps.TryJobSteps( | |
| 1352 builder_name='mac', | |
| 1353 steps=['test1', 'test2']), | |
| 1354 ], | |
| 1355 pendings=[ | |
| 1356 gen_job_pending(builder=u'mac', requested_steps=['test2'], tries=3), | |
| 1357 ], | |
| 1358 try_jobs={ | |
| 1359 key1: gen_job( | |
| 1360 build=32, | |
| 1361 builder=u'mac', | |
| 1362 completed=True, | |
| 1363 requested_steps=['test1', 'test2'], | |
| 1364 steps_failed=['test2'], | |
| 1365 steps_passed=['test1'], | |
| 1366 revision=42), | |
| 1367 key2: gen_job( | |
| 1368 builder=u'linux', | |
| 1369 build=12, | |
| 1370 completed=True, | |
| 1371 requested_steps=['test1', 'test2'], | |
| 1372 revision=22, | |
| 1373 steps_passed=['test1', 'test2']), | |
| 1374 key3: gen_job( | |
| 1375 builder=u'mac', | |
| 1376 completed=True, | |
| 1377 build=33, | |
| 1378 requested_steps=['test2'], | |
| 1379 revision=42, | |
| 1380 steps_failed=['test2'], | |
| 1381 tries=2), | |
| 1382 }) | |
| 1383 self.assertEqual(expected, self._get_verif().as_dict()) | |
| 1384 self.call_update_status( | |
| 1385 [1.] * (2 + 1 * VERBOSE), | |
| 1386 num_status=0, | |
| 1387 rietveld=[], | |
| 1388 state=base.PROCESSING, | |
| 1389 err='', | |
| 1390 need={}, | |
| 1391 waiting={'mac': ['test2']}) | |
| 1392 | |
| 1393 | |
| 1394 class RietveldTryJobsTest(TryJobOnRietveldBase): | |
| 1395 # Directly test RietveldTryJobs without constructing a TryRunnerRietveld. | |
| 1396 # They should never touch self.timestamp. | |
| 1397 def testInitial(self): | |
| 1398 now = 1. | |
| 1399 jobs = try_job_on_rietveld.RietveldTryJobs() | |
| 1400 jobs.step_verifiers = [ | |
| 1401 try_job_steps.TryJobSteps( | |
| 1402 builder_name='builder1', | |
| 1403 steps=['test10', 'test11']), | |
| 1404 ] | |
| 1405 jobs.try_jobs['key1'] = try_job_on_rietveld.RietveldTryJob( | |
| 1406 init_time=now, | |
| 1407 builder='builder1', | |
| 1408 build=12, | |
| 1409 revision=13, | |
| 1410 requested_steps=['test10'], | |
| 1411 started=int(now), | |
| 1412 steps_passed=['test10'], | |
| 1413 steps_failed=[], | |
| 1414 clobber=False, | |
| 1415 completed=True, | |
| 1416 tries=1, | |
| 1417 parent_key=None) | |
| 1418 self.assertEqual({'builder1': ['test11']}, jobs.tests_need_to_be_run(now)) | |
| 1419 self.assertEqual({'builder1': ['test11']}, jobs.tests_waiting_for_result()) | |
| 1420 | |
| 1421 def testPending(self): | |
| 1422 now = 1. | |
| 1423 jobs = try_job_on_rietveld.RietveldTryJobs() | |
| 1424 jobs.step_verifiers = [ | |
| 1425 try_job_steps.TryJobSteps( | |
| 1426 builder_name='builder1', | |
| 1427 steps=['test10', 'test11']), | |
| 1428 ] | |
| 1429 jobs.try_jobs['key1'] = try_job_on_rietveld.RietveldTryJob( | |
| 1430 init_time=now, | |
| 1431 builder='builder1', | |
| 1432 build=12, | |
| 1433 revision=13, | |
| 1434 requested_steps=['test10'], | |
| 1435 started=int(now), | |
| 1436 steps_passed=['test10'], | |
| 1437 steps_failed=[], | |
| 1438 clobber=False, | |
| 1439 completed=True, | |
| 1440 tries=1, | |
| 1441 parent_key=None) | |
| 1442 jobs.pendings.append( | |
| 1443 try_job_on_rietveld.RietveldTryJobPending( | |
| 1444 init_time=now, | |
| 1445 builder='builder1', | |
| 1446 revision=13, | |
| 1447 requested_steps=['test11'], | |
| 1448 clobber=False, | |
| 1449 tries=1)) | |
| 1450 self.assertEqual({}, jobs.tests_need_to_be_run(now)) | |
| 1451 self.assertEqual({'builder1': ['test11']}, jobs.tests_waiting_for_result()) | |
| 1452 | |
| 1453 def testTriggeredPending(self): | |
| 1454 # Construct an instance that has both tests to trigger and tests that are | |
| 1455 # pending results. | |
| 1456 now = 1. | |
| 1457 jobs = try_job_on_rietveld.RietveldTryJobs() | |
| 1458 jobs.step_verifiers = [ | |
| 1459 try_job_steps.TryJobSteps( | |
| 1460 builder_name='builder1', | |
| 1461 steps=['test10', 'test11']), | |
| 1462 try_job_steps.TryJobSteps( | |
| 1463 builder_name='builder2', | |
| 1464 steps=['test20', 'test21']), | |
| 1465 ] | |
| 1466 jobs.try_jobs['key1'] = try_job_on_rietveld.RietveldTryJob( | |
| 1467 init_time=now, | |
| 1468 builder='builder1', | |
| 1469 build=12, | |
| 1470 revision=13, | |
| 1471 requested_steps=['test10'], | |
| 1472 started=int(now), | |
| 1473 steps_passed=['test10'], | |
| 1474 steps_failed=[], | |
| 1475 clobber=False, | |
| 1476 completed=True, | |
| 1477 tries=1, | |
| 1478 parent_key=None) | |
| 1479 jobs.try_jobs['key2'] = try_job_on_rietveld.RietveldTryJob( | |
| 1480 init_time=now, | |
| 1481 builder='builder2', | |
| 1482 build=13, | |
| 1483 revision=14, | |
| 1484 requested_steps=[], | |
| 1485 started=int(now), | |
| 1486 steps_passed=['test21'], | |
| 1487 steps_failed=[], | |
| 1488 clobber=False, | |
| 1489 completed=False, | |
| 1490 tries=1, | |
| 1491 parent_key=None) | |
| 1492 jobs.pendings.append( | |
| 1493 try_job_on_rietveld.RietveldTryJobPending( | |
| 1494 init_time=now, | |
| 1495 builder='builder2', | |
| 1496 revision=14, | |
| 1497 requested_steps=['test20'], | |
| 1498 clobber=False, | |
| 1499 tries=1)) | |
| 1500 # test11 is still not queued to be run but build with test20 in it has still | |
| 1501 # not started yet. | |
| 1502 self.assertEqual({'builder1': ['test11']}, jobs.tests_need_to_be_run(now)) | |
| 1503 self.assertEqual( | |
| 1504 {'builder1': ['test11'], 'builder2': ['test20']}, | |
| 1505 jobs.tests_waiting_for_result()) | |
| 1506 | |
| 1507 def testAddTriggeredBot(self): | |
| 1508 jobs = try_job_on_rietveld.RietveldTryJobs() | |
| 1509 jobs.step_verifiers = [try_job_steps.TryJobTriggeredSteps( | |
| 1510 builder_name='tester1', | |
| 1511 trigger_name='builder1', | |
| 1512 steps={'test3': 'trigger'})] | |
| 1513 self.assertEqual({'builder1': ['trigger']}, jobs.tests_need_to_be_run(1.)) | |
| 1514 self.assertEqual({'tester1': ['test3']}, jobs.tests_waiting_for_result()) | |
| 1515 | |
| 1516 def testGenerateWatchedBuilders(self): | |
| 1517 jobs = try_job_on_rietveld.RietveldTryJobs() | |
| 1518 jobs.step_verifiers = [ | |
| 1519 try_job_steps.TryJobSteps( | |
| 1520 builder_name='builder1', | |
| 1521 steps=['test']), | |
| 1522 try_job_steps.TryJobTriggeredSteps( | |
| 1523 builder_name='triggered1', | |
| 1524 trigger_name='trigger_bot1', | |
| 1525 steps={'test': 'test'}), | |
| 1526 try_job_steps.TryJobTriggeredOrNormalSteps( | |
| 1527 builder_name='triggered2', | |
| 1528 trigger_name='trigger_bot2', | |
| 1529 trigger_bot_steps=['test'], | |
| 1530 steps={'test': 'test'}, | |
| 1531 use_triggered_bot=False) | |
| 1532 ] | |
| 1533 | |
| 1534 expected_watched_builders = [ | |
| 1535 'builder1', | |
| 1536 'trigger_bot1', | |
| 1537 'trigger_bot2', | |
| 1538 'triggered1', | |
| 1539 'triggered2' | |
| 1540 ] | |
| 1541 self.assertEqual(sorted(expected_watched_builders), | |
| 1542 sorted(jobs.watched_builders())) | |
| 1543 | |
| 1544 | |
| 1545 if __name__ == '__main__': | |
| 1546 logging.basicConfig( | |
| 1547 level=[logging.WARNING, logging.INFO, logging.DEBUG][ | |
| 1548 min(sys.argv.count('-v'), 2)], | |
| 1549 format='%(levelname)5s %(module)15s(%(lineno)3d): %(message)s') | |
| 1550 if '-v' in sys.argv: | |
| 1551 VERBOSE = True | |
| 1552 unittest.TestCase.maxDiff = None | |
| 1553 unittest.main() | |
| OLD | NEW |