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 |