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

Side by Side Diff: commit-queue/tests/pending_manager_test.py

Issue 135363007: Delete public commit queue to avoid confusion after move to internal repo (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « commit-queue/tests/natsort_test.py ('k') | commit-queue/tests/presubmit_check_test.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 pending_manager.py."""
7
8 import logging
9 import os
10 import re
11 import sys
12 import time
13 import traceback
14 import unittest
15 import urllib2
16
17 ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
18 sys.path.insert(0, os.path.join(ROOT_DIR, '..'))
19
20 import find_depot_tools # pylint: disable=W0611
21 import breakpad
22
23 import context
24 import pending_manager
25 from verification import base
26 from verification import fake
27 from verification import project_base
28 from verification import reviewer_lgtm
29
30 # In tests/
31 import mocks
32
33
34 def read(filename):
35 f = open(filename, 'rb')
36 content = f.read()
37 f.close()
38 return content
39
40
41 def write(filename, content):
42 f = open(filename, 'wb')
43 f.write(content)
44 f.close()
45
46
47 def trim(x):
48 return x.replace(' ', '').replace('\n', '')
49
50
51 def _try_comment(issue=31337):
52 return (
53 "add_comment(%d, u'%shttp://localhost/author@example.com/%d/1\\n')" %
54 (issue, pending_manager.PendingManager.TRYING_PATCH.replace('\n', '\\n'),
55 issue))
56
57
58 class TestPendingManager(mocks.TestCase):
59 def setUp(self):
60 super(TestPendingManager, self).setUp()
61 self.root_dir = ROOT_DIR
62
63 def testLoadSave(self):
64 pc = pending_manager.PendingManager(
65 context.Context(None, None, mocks.AsyncPushMock(self)),
66 [fake.FakeVerifier(base.SUCCEEDED)],
67 [])
68 filename = os.path.join(self.root_dir, 'foo.json')
69 empty = """{
70 "__persistent_type__": "PendingQueue",
71 "pending_commits": {}
72 }
73 """
74 write(filename, empty)
75 try:
76 pc.load(filename)
77 self.assertEqual(pc.queue.pending_commits, {})
78 pc.save(filename)
79 self.assertEqual(trim(empty), trim(read(filename)))
80 finally:
81 os.remove(filename)
82 if os.path.exists(filename + '.old'):
83 os.remove(filename + '.old')
84
85 def _get_pc(self, verifiers_no_patch, verifiers):
86 return pending_manager.PendingManager(
87 self.context, verifiers_no_patch, verifiers)
88
89 def _check_standard_verification(self, pc, success, defered):
90 """Verifies the checkout and rietveld calls."""
91 pc.scan_results()
92 self.assertEqual(len(pc.queue.iterate()), 0)
93 issue = 31337
94 if pc.verifiers:
95 if success:
96 self.context.checkout.check_calls(
97 [ 'prepare(None)',
98 'apply_patch(%r)' % (self.context.rietveld.patchsets[0],),
99 'prepare(None)', # Will sync to HEAD/124.
100 'apply_patch(%r)' % (self.context.rietveld.patchsets[1],),
101 (
102 "commit(u'foo\\n\\n"
103 "Review URL: http://nowhere/%d', "
104 "u'author@example.com')") % issue])
105 self.context.rietveld.check_calls(
106 [ _try_comment(),
107 'close_issue(%d)' % issue,
108 "update_description(%d, u'foo')" % issue,
109 "add_comment(%d, 'Change committed as 125')" % issue])
110 else:
111 self.context.checkout.check_calls(
112 [ 'prepare(None)',
113 'apply_patch(%r)' % (self.context.rietveld.patchsets[0],)])
114 self.context.rietveld.check_calls(
115 [ _try_comment(),
116 "set_flag(%d, 1, 'commit', False)" % issue,
117 "add_comment(%d, %r)" % (issue, pc.FAILED_NO_MESSAGE)])
118 else:
119 if success:
120 self.context.checkout.check_calls(
121 self._prepare_apply_commit(0, issue))
122 self.context.rietveld.check_calls(
123 [ _try_comment(),
124 'close_issue(%d)' % issue,
125 "update_description(%d, u'foo')" % issue,
126 "add_comment(%d, 'Change committed as 125')" % issue])
127 else:
128 # checkout is never touched in that case.
129 self.context.checkout.check_calls([])
130 if defered:
131 self.context.rietveld.check_calls(
132 [ _try_comment(),
133 "set_flag(%d, 1, 'commit', False)" % issue,
134 "add_comment(%d, %r)" % (issue, pc.FAILED_NO_MESSAGE)])
135 else:
136 self.context.rietveld.check_calls(
137 [ "set_flag(%d, 1, 'commit', False)" % issue,
138 "add_comment(%d, %r)" % (issue, pc.FAILED_NO_MESSAGE)])
139
140 def _prepare_apply_commit(self, index, issue, server_hooks_missing=False):
141 """Returns a frequent sequence of action happening on the Checkout object.
142
143 The list returned by this function should be used as an argument to
144 self.context.checkout.check_calls().
145 """
146 seq = [
147 # Reverts any previous modification or checkout the tree if it was not
148 # present.
149 'prepare(None)',
150 # Applies the requested PatchSet.
151 'apply_patch(%r)' % self.context.rietveld.patchsets[index],
152 ]
153 # Commits the patch.
154 author_and_reviewer = ''
155 if server_hooks_missing:
156 author_and_reviewer = (
157 '\\n\\nR=rev@example.com\\n\\nAuthor: author@example.com')
158 commit_message = (
159 "commit(u'foo%s\\n\\n"
160 "Review URL: http://nowhere/%d', "
161 "u'author@example.com')") % (author_and_reviewer, issue)
162 seq.append(commit_message)
163
164 return seq
165
166 def testNoVerification(self):
167 try:
168 self._get_pc([], [])
169 except ValueError:
170 pass
171 else:
172 self.fail(msg='A PendingManager must require at least one verifier.')
173
174 try:
175 # Cannot have the same verifier two times.
176 self._get_pc(
177 [fake.FakeVerifier(base.SUCCEEDED)],
178 [fake.FakeVerifier(base.SUCCEEDED)])
179 except AssertionError:
180 pass
181 else:
182 self.fail(msg='A PendingManager should not accept the same verifier'
183 ' two times.')
184
185 def _check_1(self, pc, result):
186 issue = 31337
187 # 'initial' won't be sent if the pre-patch verification fails, this is to
188 # not add noise for ignored CLs.
189 send_initial_packet = (result == base.SUCCEEDED or pc.verifiers)
190 self.assertEqual(len(pc.queue.iterate()), 0)
191 pc.look_for_new_pending_commit()
192 self.assertEqual(len(pc.queue.iterate()), 1)
193 commit = pc.queue.get(issue)
194 self.assertEqual(len(commit.verifications), 0)
195 pc.process_new_pending_commit()
196 if result == base.FAILED:
197 self.assertEqual([], pc.queue.iterate())
198 else:
199 commit = pc.queue.get(issue)
200 self.assertEqual(commit.verifications['fake'].get_state(), result)
201 self.assertEqual(len(commit.verifications), 1)
202 pc.update_status()
203 if result == base.FAILED:
204 self.assertEqual([], pc.queue.iterate())
205 else:
206 commit = pc.queue.get(issue)
207 self.assertEqual(commit.verifications['fake'].get_state(), result)
208 self.assertEqual('', commit.relpath)
209 self.assertEqual(len(commit.verifications), 1)
210 self._check_standard_verification(pc, result == base.SUCCEEDED, False)
211
212 if result == base.SUCCEEDED:
213 self.context.status.check_names(['initial', 'why not', 'commit'])
214 elif send_initial_packet:
215 self.context.status.check_names(['initial', 'abort'])
216 else:
217 # Only happens when there is no verifier that requires a patch.
218 self.context.status.check_names(['abort'])
219
220 def testNoPatchVerification(self):
221 pc = self._get_pc([fake.FakeVerifier(base.SUCCEEDED)], [])
222 self._check_1(pc, base.SUCCEEDED)
223
224 def testPatchVerification(self):
225 pc = self._get_pc([], [fake.FakeVerifier(base.SUCCEEDED)])
226 self._check_1(pc, base.SUCCEEDED)
227
228 def testNoPatchVerificationFail(self):
229 pc = self._get_pc([fake.FakeVerifier(base.FAILED)], [])
230 self._check_1(pc, base.FAILED)
231
232 def testPatchVerificationFail(self):
233 pc = self._get_pc([], [fake.FakeVerifier(base.FAILED)])
234 self._check_1(pc, base.FAILED)
235
236 def testPatchDiscardThrows(self):
237 # Handle HTTPError correctly.
238 result = []
239 issue = 31337
240 pc = self._get_pc([], [fake.FakeVerifier(base.FAILED)])
241
242 def set_flag_throw(_issue, _patchset, _flag, _value):
243 raise urllib2.HTTPError(None, None, None, None, None)
244
245 def send_stack(*_args, **_kwargs):
246 result.append(True)
247
248 self.mock(breakpad, 'SendStack', send_stack)
249 self.mock(traceback, 'print_stack', lambda: None)
250 self.mock(logging, 'error', lambda _: None)
251 pc.context.rietveld.set_flag = set_flag_throw
252
253 self.assertEqual(len(pc.queue.iterate()), 0)
254 pc.look_for_new_pending_commit()
255 self.assertEqual(len(pc.queue.iterate()), 1)
256 commit = pc.queue.get(issue)
257 self.assertEqual(len(commit.verifications), 0)
258 pc.process_new_pending_commit()
259 self.assertEqual([], pc.queue.iterate())
260 pc.update_status()
261 self.assertEqual([], pc.queue.iterate())
262 self.context.checkout.check_calls(
263 [ 'prepare(None)',
264 'apply_patch(%r)' % (self.context.rietveld.patchsets[0],),
265 ])
266 self.context.rietveld.check_calls(
267 [ _try_comment(),
268 "add_comment(%d, %r)" % (issue, pc.FAILED_NO_MESSAGE),
269 ])
270 self.context.status.check_names(['initial', 'abort'])
271
272 def _check_defer_1(self, pc, result):
273 issue = 31337
274 self.assertEqual(len(pc.queue.iterate()), 0)
275 pc.look_for_new_pending_commit()
276 self.assertEqual(len(pc.queue.iterate()), 1)
277 commit = pc.queue.get(issue)
278 self.assertEqual(len(commit.verifications), 0)
279 pc.process_new_pending_commit()
280 commit = pc.queue.get(issue)
281 self.assertEqual('', commit.relpath)
282 self.assertEqual(commit.verifications['fake'].get_state(), base.PROCESSING)
283 self.assertEqual(len(commit.verifications), 1)
284 pc.update_status()
285 commit = pc.queue.get(issue)
286 self.assertEqual('', commit.relpath)
287 self.assertEqual(commit.verifications['fake'].get_state(), result)
288 self.assertEqual(len(commit.verifications), 1)
289 self._check_standard_verification(pc, result == base.SUCCEEDED, True)
290 if result == base.SUCCEEDED:
291 self.context.status.check_names(['initial', 'why not', 'why not',
292 'why not', 'commit'])
293 else:
294 self.context.status.check_names(['initial', 'why not', 'why not',
295 'abort'])
296
297 def testDeferNoPatchVerification(self):
298 pc = self._get_pc([fake.DeferredFakeVerifier(base.SUCCEEDED, 0)], [])
299 self._check_defer_1(pc, base.SUCCEEDED)
300
301 def testDeferPatchVerification(self):
302 pc = self._get_pc([], [fake.DeferredFakeVerifier(base.SUCCEEDED, 0)])
303 self._check_defer_1(pc, base.SUCCEEDED)
304
305 def testDeferNoPatchVerificationFail(self):
306 pc = self._get_pc([fake.DeferredFakeVerifier(base.FAILED, 0)], [])
307 self._check_defer_1(pc, base.FAILED)
308
309 def testDeferPatchVerificationFail(self):
310 pc = self._get_pc([], [fake.DeferredFakeVerifier(base.FAILED, 0)])
311 self._check_defer_1(pc, base.FAILED)
312
313 def _check_4(self, f1, f2, f3, f4):
314 issue = 31337
315 fake1 = fake.FakeVerifier(f1)
316 fake1.name = 'fake1'
317 fake2 = fake.FakeVerifier(f2)
318 fake2.name = 'fake2'
319 fake3 = fake.FakeVerifier(f3)
320 fake3.name = 'fake3'
321 fake4 = fake.FakeVerifier(f4)
322 fake4.name = 'fake4'
323 nb = 1
324 if f1 is base.SUCCEEDED:
325 nb = 2
326 if f2 is base.SUCCEEDED:
327 nb = 3
328 if f3 is base.SUCCEEDED:
329 nb = 4
330 pc = self._get_pc([fake1, fake2], [fake3, fake4])
331 self.assertEqual(len(pc.queue.iterate()), 0)
332 pc.look_for_new_pending_commit()
333 self.assertEqual(len(pc.queue.iterate()), 1)
334 commit = pc.queue.get(issue)
335 self.assertEqual(len(commit.verifications), 0)
336 pc.process_new_pending_commit()
337 if not all(f == base.SUCCEEDED for f in (f1, f2, f3, f4)):
338 self.assertEqual([], pc.queue.iterate())
339 else:
340 commit = pc.queue.get(issue)
341 self.assertEqual(commit.verifications['fake1'].get_state(), f1)
342 self.assertEqual(commit.verifications['fake2'].get_state(), f2)
343 self.assertEqual(commit.verifications['fake3'].get_state(), f3)
344 self.assertEqual(commit.verifications['fake4'].get_state(), f4)
345 self.assertEqual(len(commit.verifications), nb)
346 pc.update_status()
347 if not all(f == base.SUCCEEDED for f in (f1, f2, f3, f4)):
348 self.assertEqual([], pc.queue.iterate())
349 else:
350 commit = pc.queue.get(issue)
351 self.assertEqual(commit.verifications['fake1'].get_state(), f1)
352 self.assertEqual(commit.verifications['fake2'].get_state(), f2)
353 self.assertEqual(commit.verifications['fake3'].get_state(), f3)
354 self.assertEqual(commit.verifications['fake4'].get_state(), f4)
355 self.assertEqual(len(commit.verifications), nb)
356 self._check_standard_verification(
357 pc, all(x == base.SUCCEEDED for x in (f1, f2, f3, f4)), False)
358 if all(x == base.SUCCEEDED for x in (f1, f2, f3, f4)):
359 self.context.status.check_names(['initial', 'why not', 'commit'])
360 else:
361 self.context.status.check_names(['initial', 'abort'])
362
363 def test4thVerificationFail(self):
364 self._check_4(base.SUCCEEDED, base.SUCCEEDED, base.SUCCEEDED, base.FAILED)
365
366 def test4Verification(self):
367 self._check_4(
368 base.SUCCEEDED, base.SUCCEEDED, base.SUCCEEDED, base.SUCCEEDED)
369
370 def test4Verification3rdFail(self):
371 self._check_4(base.SUCCEEDED, base.SUCCEEDED, base.FAILED, base.SUCCEEDED)
372
373 def _check_defer_4(self, f1, f2, f3, f4):
374 issue = 31337
375 fake1 = fake.DeferredFakeVerifier(f1, 0)
376 fake1.name = 'fake1'
377 fake2 = fake.DeferredFakeVerifier(f2, 0)
378 fake2.name = 'fake2'
379 fake3 = fake.DeferredFakeVerifier(f3, 0)
380 fake3.name = 'fake3'
381 fake4 = fake.DeferredFakeVerifier(f4, 0)
382 fake4.name = 'fake4'
383 pc = self._get_pc([fake1, fake2], [fake3, fake4])
384 self.assertEqual(len(pc.queue.iterate()), 0)
385 pc.look_for_new_pending_commit()
386 self.assertEqual(len(pc.queue.iterate()), 1)
387 commit = pc.queue.get(issue)
388 self.assertEqual(len(commit.verifications), 0)
389 pc.process_new_pending_commit()
390 commit = pc.queue.get(issue)
391 self.assertEqual(
392 commit.verifications['fake1'].get_state(), base.PROCESSING)
393 self.assertEqual(
394 commit.verifications['fake2'].get_state(), base.PROCESSING)
395 self.assertEqual(
396 commit.verifications['fake3'].get_state(), base.PROCESSING)
397 self.assertEqual(
398 commit.verifications['fake4'].get_state(), base.PROCESSING)
399 self.assertEqual(len(commit.verifications), 4)
400 pc.update_status()
401 self.assertEqual(commit.verifications['fake1'].get_state(), f1)
402 self.assertEqual(commit.verifications['fake2'].get_state(), f2)
403 self.assertEqual(commit.verifications['fake3'].get_state(), f3)
404 self.assertEqual(commit.verifications['fake4'].get_state(), f4)
405 self.assertEqual('', commit.relpath)
406 self._check_standard_verification(
407 pc, all(x == base.SUCCEEDED for x in (f1, f2, f3, f4)), False)
408 if all(x == base.SUCCEEDED for x in (f1, f2, f3, f4)):
409 self.context.status.check_names(['initial', 'why not', 'why not',
410 'why not', 'commit'])
411 else:
412 self.context.status.check_names(['initial', 'why not', 'why not',
413 'abort'])
414
415 def testDefer4thVerificationFail(self):
416 self._check_defer_4(
417 base.SUCCEEDED, base.SUCCEEDED, base.SUCCEEDED, base.FAILED)
418
419 def testDefer4Verification(self):
420 self._check_defer_4(
421 base.SUCCEEDED, base.SUCCEEDED, base.SUCCEEDED, base.SUCCEEDED)
422
423 def testDefer4Verification3rdFail(self):
424 self._check_defer_4(
425 base.SUCCEEDED, base.SUCCEEDED, base.FAILED, base.SUCCEEDED)
426
427 def testRelPath(self):
428 issue = 31337
429 verifiers = [
430 project_base.ProjectBaseUrlVerifier(
431 [r'^%s(.*)$' % re.escape(r'http://example.com/')]),
432 ]
433 pc = self._get_pc([], verifiers)
434 pc.context.rietveld.issues[issue]['base_url'] = 'http://example.com/sub/dir'
435 pc.look_for_new_pending_commit()
436 self.assertEqual(1, len(pc.queue.iterate()))
437 pc.process_new_pending_commit()
438 self.assertEqual('sub/dir', pc.queue.get(issue).relpath)
439 self.context.checkout.check_calls(
440 [ 'prepare(None)',
441 'apply_patch(%r)' % (self.context.rietveld.patchsets[0],)])
442 pc.update_status()
443 self.context.checkout.check_calls([])
444 pc.scan_results()
445 self.context.checkout.check_calls(
446 # Will sync to HEAD, 124.
447 self._prepare_apply_commit(1, issue))
448 self.context.rietveld.check_calls(
449 [ _try_comment(),
450 'close_issue(%d)' % issue,
451 "update_description(%d, u'foo')" % issue,
452 "add_comment(%d, 'Change committed as 125')" % issue])
453 self.context.status.check_names(['initial', 'why not', 'commit'])
454
455 def testCommitBurst(self):
456 issue = 31337
457 pc = self._get_pc([fake.FakeVerifier(base.SUCCEEDED)], [])
458 self.assertEqual(4, pc.MAX_COMMIT_BURST)
459 timestamp = [1]
460 self.mock(time, 'time', lambda: timestamp[-1])
461 for i in range(pc.MAX_COMMIT_BURST + 2):
462 self.context.rietveld.issues[i] = (
463 self.context.rietveld.issues[issue].copy())
464 self.context.rietveld.issues[i]['issue'] = i
465 pc.look_for_new_pending_commit()
466 self.assertEqual(len(pc.queue.iterate()), pc.MAX_COMMIT_BURST + 3)
467 pc.process_new_pending_commit()
468 pc.update_status()
469 pc.scan_results()
470 self.context.checkout.check_calls(
471 self._prepare_apply_commit(0, 0) +
472 self._prepare_apply_commit(1, 1) +
473 self._prepare_apply_commit(2, 2) +
474 self._prepare_apply_commit(3, 3))
475 self.context.rietveld.check_calls(
476 [ _try_comment(0),
477 _try_comment(1),
478 _try_comment(2),
479 _try_comment(3),
480 _try_comment(4),
481 _try_comment(5),
482 _try_comment(),
483 'close_issue(0)',
484 "update_description(0, u'foo')",
485 "add_comment(0, 'Change committed as 125')",
486 'close_issue(1)',
487 "update_description(1, u'foo')",
488 "add_comment(1, 'Change committed as 125')",
489 'close_issue(2)',
490 "update_description(2, u'foo')",
491 "add_comment(2, 'Change committed as 125')",
492 'close_issue(3)',
493 "update_description(3, u'foo')",
494 "add_comment(3, 'Change committed as 125')",
495 ])
496 self.assertEqual(3, len(pc.queue.iterate()))
497 total = pc.MAX_COMMIT_BURST + 3
498 self.context.status.check_names(['initial'] * total +
499 (['why not', 'commit'] *
500 pc.MAX_COMMIT_BURST) +
501 ['why not'] * 3)
502
503 # Dry run.
504 pc.scan_results()
505 self.context.checkout.check_calls([])
506 self.context.rietveld.check_calls([])
507 self.context.status.check_names(['why not'] * 3)
508
509 # Remove one item from the burst.
510 pc.recent_commit_timestamps.pop()
511 pc.scan_results()
512 next_item = pc.MAX_COMMIT_BURST
513 self.context.checkout.check_calls(
514 self._prepare_apply_commit(next_item, next_item))
515 self.context.rietveld.check_calls(
516 [ 'close_issue(%d)' % next_item,
517 "update_description(%d, u'foo')" % next_item,
518 "add_comment(%d, 'Change committed as 125')" % next_item,
519 ])
520 self.context.status.check_names(['why not', 'commit'] + ['why not'] * 2)
521 # After a delay, must flush the queue.
522 timestamp.append(timestamp[-1] + pc.COMMIT_BURST_DELAY + 1)
523 pc.scan_results()
524 self.context.checkout.check_calls(
525 self._prepare_apply_commit(next_item + 1, next_item + 1) +
526 self._prepare_apply_commit(next_item + 2, issue))
527 self.context.rietveld.check_calls(
528 [ 'close_issue(%d)' % (next_item + 1),
529 "update_description(%d, u'foo')" % (next_item + 1),
530 "add_comment(%d, 'Change committed as 125')" % (next_item + 1),
531 'close_issue(%d)' % issue,
532 "update_description(%d, u'foo')" % issue,
533 "add_comment(%d, 'Change committed as 125')" % issue])
534 self.context.status.check_names(['why not', 'commit'] * 2)
535
536 def testIgnored(self):
537 issue = 31337
538 verifiers = [
539 project_base.ProjectBaseUrlVerifier(
540 [r'^%s(.*)$' % re.escape(r'http://example.com/')]),
541 ]
542 pc = self._get_pc(verifiers, [])
543 pc.context.rietveld.issues[issue]['base_url'] = 'http://unrelated.com/sub'
544 pc.look_for_new_pending_commit()
545 pc.process_new_pending_commit()
546 pc.update_status()
547 pc.scan_results()
548 self.assertEqual(1, len(pc.queue.iterate()))
549 self.assertEqual('', pc.queue.get(issue).relpath)
550 self.assertEqual(base.IGNORED, pc.queue.get(issue).get_state())
551
552 def testServerHooksMissing(self):
553 issue = 31337
554 verifiers = [
555 project_base.ProjectBaseUrlVerifier(
556 [r'^%s(.*)$' % re.escape(r'http://example.com/')]),
557 ]
558 self.context.server_hooks_missing = True
559 pc = self._get_pc(verifiers, [])
560 pc.context.rietveld.issues[issue]['base_url'] = 'http://example.com/'
561 pc.look_for_new_pending_commit()
562 pc.process_new_pending_commit()
563 pc.update_status()
564 pc.scan_results()
565 self.context.rietveld.check_calls(
566 [ _try_comment(),
567 'close_issue(%d)' % issue,
568 "update_description(%d, u'foo')" % issue,
569 "add_comment(%d, 'Change committed as 125')" % issue])
570 self.context.status.check_names(['initial', 'why not', 'commit'])
571 self.context.checkout.check_calls(
572 self._prepare_apply_commit(0, issue, server_hooks_missing=True))
573
574 def testDisapeared(self):
575 issue = 31337
576 verifiers = [
577 project_base.ProjectBaseUrlVerifier(
578 [r'^%s(.*)$' % re.escape(r'http://example.com/')]),
579 ]
580 pc = self._get_pc(verifiers, [])
581 pc.context.rietveld.issues[issue]['base_url'] = 'http://unrelated.com/sub'
582 pc.look_for_new_pending_commit()
583 pc.process_new_pending_commit()
584 pc.update_status()
585 pc.scan_results()
586 self.assertEqual(1, len(pc.queue.iterate()))
587 del pc.context.rietveld.issues[issue]
588 pc.look_for_new_pending_commit()
589 pc.process_new_pending_commit()
590 pc.update_status()
591 pc.scan_results()
592 self.assertEqual(0, len(pc.queue.iterate()))
593 self.context.status.check_names(['abort'])
594
595 def _get_pc_reviewer(self):
596 verifiers = [
597 reviewer_lgtm.ReviewerLgtmVerifier(
598 ['.*'], [re.escape('commit-bot@example.com')])
599 ]
600 pc = self._get_pc(verifiers, [])
601 return pc
602
603 def _approve(self, sender=None):
604 issue = 31337
605 if not sender:
606 sender = self.context.rietveld.issues[issue]['reviewers'][0]
607 self.context.rietveld.issues[issue]['messages'].append(
608 {
609 'approval': True,
610 'sender': sender,
611 })
612
613 def testVerifyDefaultMock(self):
614 # Verify mock expectation for the default settings.
615 issue = 31337
616 pc = self._get_pc_reviewer()
617 self.assertEqual(0, len(pc.queue.iterate()))
618 pc.look_for_new_pending_commit()
619 self.assertEqual(1, len(pc.queue.iterate()))
620 # Pop the LGTM.
621 pc.queue.iterate()[0].messages.pop(1)
622 pc.process_new_pending_commit()
623 self.assertEqual(0, len(pc.queue.iterate()))
624 pc.update_status()
625 self.assertEqual(0, len(pc.queue.iterate()))
626 self.context.rietveld.check_calls(
627 [ "set_flag(%d, 1, 'commit', False)" % issue,
628 "add_comment(%d, %r)" % (issue, reviewer_lgtm.LgtmStatus.NO_LGTM)])
629 self.context.status.check_names(['abort'])
630
631 def testVerifyDefaultMockPlusLGTM(self):
632 # Verify mock expectation with a single approval message.
633 issue = 31337
634 pc = self._get_pc_reviewer()
635 self._approve()
636 self.assertEqual(0, len(pc.queue.iterate()))
637 pc.look_for_new_pending_commit()
638 self.assertEqual(1, len(pc.queue.iterate()))
639 pc.process_new_pending_commit()
640 self.assertEqual(1, len(pc.queue.iterate()))
641 pc.update_status()
642 self.assertEqual(1, len(pc.queue.iterate()))
643 pc.scan_results()
644 self.assertEqual(0, len(pc.queue.iterate()))
645 self.context.rietveld.check_calls(
646 [ _try_comment(),
647 'close_issue(%d)' % issue,
648 "update_description(%d, u'foo')" % issue,
649 "add_comment(%d, 'Change committed as 125')" % issue])
650 self.context.status.check_names(['initial', 'why not', 'commit'])
651 self.context.checkout.check_calls(
652 self._prepare_apply_commit(0, issue))
653
654 def testDriveBy(self):
655 issue = 31337
656 pc = self._get_pc_reviewer()
657 self._approve()
658 pc.look_for_new_pending_commit()
659 pc.process_new_pending_commit()
660 pc.update_status()
661 # A new reviewer prevents the commit.
662 i = self.context.rietveld.issues[issue]
663 i['reviewers'] = i['reviewers'] + ['annoying@dude.org']
664 pc.scan_results()
665 self.context.rietveld.check_calls(
666 [ _try_comment(),
667 "set_flag(%d, 1, 'commit', False)" % issue,
668 ('add_comment(%d, "List of reviewers changed. annoying@dude.org '
669 'did a drive-by without LGTM\'ing!")') % issue])
670 self.context.status.check_names(['initial', 'abort'])
671
672 def testDriveByLGTM(self):
673 issue = 31337
674 pc = self._get_pc_reviewer()
675 self._approve()
676 pc.look_for_new_pending_commit()
677 pc.process_new_pending_commit()
678 pc.update_status()
679 # He's nice, he left a LGTM.
680 i = self.context.rietveld.issues[issue]
681 i['reviewers'] = i['reviewers'] + ['nice@dude.org']
682 self._approve('nice@dude.org')
683 pc.scan_results()
684 self.assertEqual(0, len(pc.queue.iterate()))
685 self.context.rietveld.check_calls(
686 [ _try_comment(),
687 'close_issue(%d)' % issue,
688 "update_description(%d, u'foo')" % issue,
689 "add_comment(%d, 'Change committed as 125')" % issue])
690 self.context.status.check_names(['initial', 'why not', 'commit'])
691 self.context.checkout.check_calls(
692 self._prepare_apply_commit(0, issue))
693
694 def testWhyNotUpdates(self):
695 issue = 31337
696 fake1_change = 1
697 fake1 = fake.DeferredFakeVerifier(base.SUCCEEDED, fake1_change)
698 fake1.name = 'fake1'
699
700 fake2_change = 3
701 fake2 = fake.DeferredFakeVerifier(base.SUCCEEDED, fake2_change)
702 fake2.name = 'fake2'
703 pc = self._get_pc([fake1, fake2], [])
704 pc.look_for_new_pending_commit()
705 pc.process_new_pending_commit()
706
707 self.context.status.check_names(['initial', 'why not'])
708
709 # Make sure the 'why not' is only pushed when it changes.
710 for i in range(fake2_change * 2):
711 expected = ['why not'] if fake1_change == i or fake2_change == i else []
712 pc.update_status()
713 self.context.status.check_names(expected)
714
715 pc.scan_results()
716
717 self.context.rietveld.check_calls(
718 [_try_comment(),
719 'close_issue(%d)' % issue,
720 "update_description(%d, u'foo')" % issue,
721 "add_comment(%d, 'Change committed as 125')" % issue])
722 self.context.status.check_names(['why not', 'commit'])
723 self.context.checkout.check_calls(
724 self._prepare_apply_commit(0, issue))
725
726
727 if __name__ == '__main__':
728 logging.basicConfig(
729 level=[logging.ERROR, logging.WARNING, logging.INFO, logging.DEBUG][
730 min(sys.argv.count('-v'), 3)],
731 format='%(levelname)5s %(module)15s(%(lineno)3d): %(message)s')
732 unittest.main()
OLDNEW
« no previous file with comments | « commit-queue/tests/natsort_test.py ('k') | commit-queue/tests/presubmit_check_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698