blob: c711e4d954b1a9948e7243e03d29d07ea1afd36b [file] [log] [blame]
James E. Blair351d47d2018-01-08 09:31:30 -08001#!/usr/bin/env python
2
3# Copyright 2012 Hewlett-Packard Development Company, L.P.
4#
5# Licensed under the Apache License, Version 2.0 (the "License"); you may
6# not use this file except in compliance with the License. You may obtain
7# a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations
15# under the License.
16
17from tests.base import (
18 ZuulTestCase,
19 simple_layout,
20)
21
22
23class TestGerritLegacyCRD(ZuulTestCase):
24 tenant_config_file = 'config/single-tenant/main.yaml'
25
26 def test_crd_gate(self):
27 "Test cross-repo dependencies"
28 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
29 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
30 A.addApproval('Code-Review', 2)
31 B.addApproval('Code-Review', 2)
32
33 AM2 = self.fake_gerrit.addFakeChange('org/project1', 'master', 'AM2')
34 AM1 = self.fake_gerrit.addFakeChange('org/project1', 'master', 'AM1')
35 AM2.setMerged()
36 AM1.setMerged()
37
38 BM2 = self.fake_gerrit.addFakeChange('org/project2', 'master', 'BM2')
39 BM1 = self.fake_gerrit.addFakeChange('org/project2', 'master', 'BM1')
40 BM2.setMerged()
41 BM1.setMerged()
42
43 # A -> AM1 -> AM2
44 # B -> BM1 -> BM2
45 # A Depends-On: B
46 # M2 is here to make sure it is never queried. If it is, it
47 # means zuul is walking down the entire history of merged
48 # changes.
49
50 B.setDependsOn(BM1, 1)
51 BM1.setDependsOn(BM2, 1)
52
53 A.setDependsOn(AM1, 1)
54 AM1.setDependsOn(AM2, 1)
55
56 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
57 A.subject, B.data['id'])
58
59 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
60 self.waitUntilSettled()
61
62 self.assertEqual(A.data['status'], 'NEW')
63 self.assertEqual(B.data['status'], 'NEW')
64
65 for connection in self.connections.connections.values():
66 connection.maintainCache([])
67
68 self.executor_server.hold_jobs_in_build = True
69 B.addApproval('Approved', 1)
70 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
71 self.waitUntilSettled()
72
73 self.executor_server.release('.*-merge')
74 self.waitUntilSettled()
75 self.executor_server.release('.*-merge')
76 self.waitUntilSettled()
77 self.executor_server.hold_jobs_in_build = False
78 self.executor_server.release()
79 self.waitUntilSettled()
80
81 self.assertEqual(AM2.queried, 0)
82 self.assertEqual(BM2.queried, 0)
83 self.assertEqual(A.data['status'], 'MERGED')
84 self.assertEqual(B.data['status'], 'MERGED')
85 self.assertEqual(A.reported, 2)
86 self.assertEqual(B.reported, 2)
87
88 changes = self.getJobFromHistory(
89 'project-merge', 'org/project1').changes
90 self.assertEqual(changes, '2,1 1,1')
91
92 def test_crd_branch(self):
93 "Test cross-repo dependencies in multiple branches"
94
95 self.create_branch('org/project2', 'mp')
96 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
97 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
98 C1 = self.fake_gerrit.addFakeChange('org/project2', 'mp', 'C1')
99 C2 = self.fake_gerrit.addFakeChange('org/project2', 'mp', 'C2',
100 status='ABANDONED')
101 C1.data['id'] = B.data['id']
102 C2.data['id'] = B.data['id']
103
104 A.addApproval('Code-Review', 2)
105 B.addApproval('Code-Review', 2)
106 C1.addApproval('Code-Review', 2)
107
108 # A Depends-On: B+C1
109 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
110 A.subject, B.data['id'])
111
112 self.executor_server.hold_jobs_in_build = True
113 B.addApproval('Approved', 1)
114 C1.addApproval('Approved', 1)
115 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
116 self.waitUntilSettled()
117
118 self.executor_server.release('.*-merge')
119 self.waitUntilSettled()
120 self.executor_server.release('.*-merge')
121 self.waitUntilSettled()
122 self.executor_server.release('.*-merge')
123 self.waitUntilSettled()
124 self.executor_server.hold_jobs_in_build = False
125 self.executor_server.release()
126 self.waitUntilSettled()
127
128 self.assertEqual(A.data['status'], 'MERGED')
129 self.assertEqual(B.data['status'], 'MERGED')
130 self.assertEqual(C1.data['status'], 'MERGED')
131 self.assertEqual(A.reported, 2)
132 self.assertEqual(B.reported, 2)
133 self.assertEqual(C1.reported, 2)
134
135 changes = self.getJobFromHistory(
136 'project-merge', 'org/project1').changes
137 self.assertEqual(changes, '2,1 3,1 1,1')
138
139 def test_crd_multiline(self):
140 "Test multiple depends-on lines in commit"
141 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
142 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
143 C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
144 A.addApproval('Code-Review', 2)
145 B.addApproval('Code-Review', 2)
146 C.addApproval('Code-Review', 2)
147
148 # A Depends-On: B+C
149 A.data['commitMessage'] = '%s\n\nDepends-On: %s\nDepends-On: %s\n' % (
150 A.subject, B.data['id'], C.data['id'])
151
152 self.executor_server.hold_jobs_in_build = True
153 B.addApproval('Approved', 1)
154 C.addApproval('Approved', 1)
155 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
156 self.waitUntilSettled()
157
158 self.executor_server.release('.*-merge')
159 self.waitUntilSettled()
160 self.executor_server.release('.*-merge')
161 self.waitUntilSettled()
162 self.executor_server.release('.*-merge')
163 self.waitUntilSettled()
164 self.executor_server.hold_jobs_in_build = False
165 self.executor_server.release()
166 self.waitUntilSettled()
167
168 self.assertEqual(A.data['status'], 'MERGED')
169 self.assertEqual(B.data['status'], 'MERGED')
170 self.assertEqual(C.data['status'], 'MERGED')
171 self.assertEqual(A.reported, 2)
172 self.assertEqual(B.reported, 2)
173 self.assertEqual(C.reported, 2)
174
175 changes = self.getJobFromHistory(
176 'project-merge', 'org/project1').changes
177 self.assertEqual(changes, '2,1 3,1 1,1')
178
179 def test_crd_unshared_gate(self):
180 "Test cross-repo dependencies in unshared gate queues"
181 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
182 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
183 A.addApproval('Code-Review', 2)
184 B.addApproval('Code-Review', 2)
185
186 # A Depends-On: B
187 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
188 A.subject, B.data['id'])
189
190 # A and B do not share a queue, make sure that A is unable to
191 # enqueue B (and therefore, A is unable to be enqueued).
192 B.addApproval('Approved', 1)
193 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
194 self.waitUntilSettled()
195
196 self.assertEqual(A.data['status'], 'NEW')
197 self.assertEqual(B.data['status'], 'NEW')
198 self.assertEqual(A.reported, 0)
199 self.assertEqual(B.reported, 0)
200 self.assertEqual(len(self.history), 0)
201
202 # Enqueue and merge B alone.
203 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
204 self.waitUntilSettled()
205
206 self.assertEqual(B.data['status'], 'MERGED')
207 self.assertEqual(B.reported, 2)
208
209 # Now that B is merged, A should be able to be enqueued and
210 # merged.
211 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
212 self.waitUntilSettled()
213
214 self.assertEqual(A.data['status'], 'MERGED')
215 self.assertEqual(A.reported, 2)
216
217 def test_crd_gate_reverse(self):
218 "Test reverse cross-repo dependencies"
219 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
220 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
221 A.addApproval('Code-Review', 2)
222 B.addApproval('Code-Review', 2)
223
224 # A Depends-On: B
225
226 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
227 A.subject, B.data['id'])
228
229 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
230 self.waitUntilSettled()
231
232 self.assertEqual(A.data['status'], 'NEW')
233 self.assertEqual(B.data['status'], 'NEW')
234
235 self.executor_server.hold_jobs_in_build = True
236 A.addApproval('Approved', 1)
237 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
238 self.waitUntilSettled()
239
240 self.executor_server.release('.*-merge')
241 self.waitUntilSettled()
242 self.executor_server.release('.*-merge')
243 self.waitUntilSettled()
244 self.executor_server.hold_jobs_in_build = False
245 self.executor_server.release()
246 self.waitUntilSettled()
247
248 self.assertEqual(A.data['status'], 'MERGED')
249 self.assertEqual(B.data['status'], 'MERGED')
250 self.assertEqual(A.reported, 2)
251 self.assertEqual(B.reported, 2)
252
253 changes = self.getJobFromHistory(
254 'project-merge', 'org/project1').changes
255 self.assertEqual(changes, '2,1 1,1')
256
257 def test_crd_cycle(self):
258 "Test cross-repo dependency cycles"
259 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
260 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
261 A.addApproval('Code-Review', 2)
262 B.addApproval('Code-Review', 2)
263
264 # A -> B -> A (via commit-depends)
265
266 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
267 A.subject, B.data['id'])
268 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
269 B.subject, A.data['id'])
270
271 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
272 self.waitUntilSettled()
273
274 self.assertEqual(A.reported, 0)
275 self.assertEqual(B.reported, 0)
276 self.assertEqual(A.data['status'], 'NEW')
277 self.assertEqual(B.data['status'], 'NEW')
278
279 def test_crd_gate_unknown(self):
280 "Test unknown projects in dependent pipeline"
281 self.init_repo("org/unknown", tag='init')
282 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
283 B = self.fake_gerrit.addFakeChange('org/unknown', 'master', 'B')
284 A.addApproval('Code-Review', 2)
285 B.addApproval('Code-Review', 2)
286
287 # A Depends-On: B
288 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
289 A.subject, B.data['id'])
290
291 B.addApproval('Approved', 1)
292 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
293 self.waitUntilSettled()
294
295 # Unknown projects cannot share a queue with any other
296 # since they don't have common jobs with any other (they have no jobs).
297 # Changes which depend on unknown project changes
298 # should not be processed in dependent pipeline
299 self.assertEqual(A.data['status'], 'NEW')
300 self.assertEqual(B.data['status'], 'NEW')
301 self.assertEqual(A.reported, 0)
302 self.assertEqual(B.reported, 0)
303 self.assertEqual(len(self.history), 0)
304
305 # Simulate change B being gated outside this layout Set the
306 # change merged before submitting the event so that when the
307 # event triggers a gerrit query to update the change, we get
308 # the information that it was merged.
309 B.setMerged()
310 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
311 self.waitUntilSettled()
312 self.assertEqual(len(self.history), 0)
313
314 # Now that B is merged, A should be able to be enqueued and
315 # merged.
316 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
317 self.waitUntilSettled()
318
319 self.assertEqual(A.data['status'], 'MERGED')
320 self.assertEqual(A.reported, 2)
321 self.assertEqual(B.data['status'], 'MERGED')
322 self.assertEqual(B.reported, 0)
323
324 def test_crd_check(self):
325 "Test cross-repo dependencies in independent pipelines"
326
327 self.executor_server.hold_jobs_in_build = True
328 self.gearman_server.hold_jobs_in_queue = True
329 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
330 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
331
332 # A Depends-On: B
333 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
334 A.subject, B.data['id'])
335
336 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
337 self.waitUntilSettled()
338
339 self.gearman_server.hold_jobs_in_queue = False
340 self.gearman_server.release()
341 self.waitUntilSettled()
342
343 self.executor_server.release('.*-merge')
344 self.waitUntilSettled()
345
346 self.assertTrue(self.builds[0].hasChanges(A, B))
347
348 self.executor_server.hold_jobs_in_build = False
349 self.executor_server.release()
350 self.waitUntilSettled()
351
352 self.assertEqual(A.data['status'], 'NEW')
353 self.assertEqual(B.data['status'], 'NEW')
354 self.assertEqual(A.reported, 1)
355 self.assertEqual(B.reported, 0)
356
357 self.assertEqual(self.history[0].changes, '2,1 1,1')
358 tenant = self.sched.abide.tenants.get('tenant-one')
359 self.assertEqual(len(tenant.layout.pipelines['check'].queues), 0)
360
361 def test_crd_check_git_depends(self):
362 "Test single-repo dependencies in independent pipelines"
363 self.gearman_server.hold_jobs_in_build = True
364 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
365 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
366
367 # Add two git-dependent changes and make sure they both report
368 # success.
369 B.setDependsOn(A, 1)
370 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
371 self.waitUntilSettled()
372 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
373 self.waitUntilSettled()
374
375 self.orderedRelease()
376 self.gearman_server.hold_jobs_in_build = False
377 self.waitUntilSettled()
378
379 self.assertEqual(A.data['status'], 'NEW')
380 self.assertEqual(B.data['status'], 'NEW')
381 self.assertEqual(A.reported, 1)
382 self.assertEqual(B.reported, 1)
383
384 self.assertEqual(self.history[0].changes, '1,1')
385 self.assertEqual(self.history[-1].changes, '1,1 2,1')
386 tenant = self.sched.abide.tenants.get('tenant-one')
387 self.assertEqual(len(tenant.layout.pipelines['check'].queues), 0)
388
389 self.assertIn('Build succeeded', A.messages[0])
390 self.assertIn('Build succeeded', B.messages[0])
391
392 def test_crd_check_duplicate(self):
393 "Test duplicate check in independent pipelines"
394 self.executor_server.hold_jobs_in_build = True
395 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
396 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
397 tenant = self.sched.abide.tenants.get('tenant-one')
398 check_pipeline = tenant.layout.pipelines['check']
399
400 # Add two git-dependent changes...
401 B.setDependsOn(A, 1)
402 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
403 self.waitUntilSettled()
404 self.assertEqual(len(check_pipeline.getAllItems()), 2)
405
406 # ...make sure the live one is not duplicated...
407 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
408 self.waitUntilSettled()
409 self.assertEqual(len(check_pipeline.getAllItems()), 2)
410
411 # ...but the non-live one is able to be.
412 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
413 self.waitUntilSettled()
414 self.assertEqual(len(check_pipeline.getAllItems()), 3)
415
416 # Release jobs in order to avoid races with change A jobs
417 # finishing before change B jobs.
418 self.orderedRelease()
419 self.executor_server.hold_jobs_in_build = False
420 self.executor_server.release()
421 self.waitUntilSettled()
422
423 self.assertEqual(A.data['status'], 'NEW')
424 self.assertEqual(B.data['status'], 'NEW')
425 self.assertEqual(A.reported, 1)
426 self.assertEqual(B.reported, 1)
427
428 self.assertEqual(self.history[0].changes, '1,1 2,1')
429 self.assertEqual(self.history[1].changes, '1,1')
430 self.assertEqual(len(tenant.layout.pipelines['check'].queues), 0)
431
432 self.assertIn('Build succeeded', A.messages[0])
433 self.assertIn('Build succeeded', B.messages[0])
434
435 def _test_crd_check_reconfiguration(self, project1, project2):
436 "Test cross-repo dependencies re-enqueued in independent pipelines"
437
438 self.gearman_server.hold_jobs_in_queue = True
439 A = self.fake_gerrit.addFakeChange(project1, 'master', 'A')
440 B = self.fake_gerrit.addFakeChange(project2, 'master', 'B')
441
442 # A Depends-On: B
443 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
444 A.subject, B.data['id'])
445
446 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
447 self.waitUntilSettled()
448
449 self.sched.reconfigure(self.config)
450
451 # Make sure the items still share a change queue, and the
452 # first one is not live.
453 tenant = self.sched.abide.tenants.get('tenant-one')
454 self.assertEqual(len(tenant.layout.pipelines['check'].queues), 1)
455 queue = tenant.layout.pipelines['check'].queues[0]
456 first_item = queue.queue[0]
457 for item in queue.queue:
458 self.assertEqual(item.queue, first_item.queue)
459 self.assertFalse(first_item.live)
460 self.assertTrue(queue.queue[1].live)
461
462 self.gearman_server.hold_jobs_in_queue = False
463 self.gearman_server.release()
464 self.waitUntilSettled()
465
466 self.assertEqual(A.data['status'], 'NEW')
467 self.assertEqual(B.data['status'], 'NEW')
468 self.assertEqual(A.reported, 1)
469 self.assertEqual(B.reported, 0)
470
471 self.assertEqual(self.history[0].changes, '2,1 1,1')
472 self.assertEqual(len(tenant.layout.pipelines['check'].queues), 0)
473
474 def test_crd_check_reconfiguration(self):
475 self._test_crd_check_reconfiguration('org/project1', 'org/project2')
476
477 def test_crd_undefined_project(self):
478 """Test that undefined projects in dependencies are handled for
479 independent pipelines"""
480 # It's a hack for fake gerrit,
481 # as it implies repo creation upon the creation of any change
482 self.init_repo("org/unknown", tag='init')
483 self._test_crd_check_reconfiguration('org/project1', 'org/unknown')
484
485 @simple_layout('layouts/ignore-dependencies.yaml')
486 def test_crd_check_ignore_dependencies(self):
487 "Test cross-repo dependencies can be ignored"
488
489 self.gearman_server.hold_jobs_in_queue = True
490 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
491 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
492 C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
493
494 # A Depends-On: B
495 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
496 A.subject, B.data['id'])
497 # C git-depends on B
498 C.setDependsOn(B, 1)
499 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
500 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
501 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
502 self.waitUntilSettled()
503
504 # Make sure none of the items share a change queue, and all
505 # are live.
506 tenant = self.sched.abide.tenants.get('tenant-one')
507 check_pipeline = tenant.layout.pipelines['check']
508 self.assertEqual(len(check_pipeline.queues), 3)
509 self.assertEqual(len(check_pipeline.getAllItems()), 3)
510 for item in check_pipeline.getAllItems():
511 self.assertTrue(item.live)
512
513 self.gearman_server.hold_jobs_in_queue = False
514 self.gearman_server.release()
515 self.waitUntilSettled()
516
517 self.assertEqual(A.data['status'], 'NEW')
518 self.assertEqual(B.data['status'], 'NEW')
519 self.assertEqual(C.data['status'], 'NEW')
520 self.assertEqual(A.reported, 1)
521 self.assertEqual(B.reported, 1)
522 self.assertEqual(C.reported, 1)
523
524 # Each job should have tested exactly one change
525 for job in self.history:
526 self.assertEqual(len(job.changes.split()), 1)
527
528 @simple_layout('layouts/three-projects.yaml')
529 def test_crd_check_transitive(self):
530 "Test transitive cross-repo dependencies"
531 # Specifically, if A -> B -> C, and C gets a new patchset and
532 # A gets a new patchset, ensure the test of A,2 includes B,1
533 # and C,2 (not C,1 which would indicate stale data in the
534 # cache for B).
535 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
536 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
537 C = self.fake_gerrit.addFakeChange('org/project3', 'master', 'C')
538
539 # A Depends-On: B
540 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
541 A.subject, B.data['id'])
542
543 # B Depends-On: C
544 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
545 B.subject, C.data['id'])
546
547 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
548 self.waitUntilSettled()
549 self.assertEqual(self.history[-1].changes, '3,1 2,1 1,1')
550
551 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
552 self.waitUntilSettled()
553 self.assertEqual(self.history[-1].changes, '3,1 2,1')
554
555 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
556 self.waitUntilSettled()
557 self.assertEqual(self.history[-1].changes, '3,1')
558
559 C.addPatchset()
560 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(2))
561 self.waitUntilSettled()
562 self.assertEqual(self.history[-1].changes, '3,2')
563
564 A.addPatchset()
565 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
566 self.waitUntilSettled()
567 self.assertEqual(self.history[-1].changes, '3,2 2,1 1,2')
568
569 def test_crd_check_unknown(self):
570 "Test unknown projects in independent pipeline"
571 self.init_repo("org/unknown", tag='init')
572 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
573 B = self.fake_gerrit.addFakeChange('org/unknown', 'master', 'D')
574 # A Depends-On: B
575 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
576 A.subject, B.data['id'])
577
578 # Make sure zuul has seen an event on B.
579 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
580 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
581 self.waitUntilSettled()
582
583 self.assertEqual(A.data['status'], 'NEW')
584 self.assertEqual(A.reported, 1)
585 self.assertEqual(B.data['status'], 'NEW')
586 self.assertEqual(B.reported, 0)
587
588 def test_crd_cycle_join(self):
589 "Test an updated change creates a cycle"
590 A = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A')
591
592 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
593 self.waitUntilSettled()
594 self.assertEqual(A.reported, 1)
595
596 # Create B->A
597 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
598 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
599 B.subject, A.data['id'])
600 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
601 self.waitUntilSettled()
602
603 # Dep is there so zuul should have reported on B
604 self.assertEqual(B.reported, 1)
605
606 # Update A to add A->B (a cycle).
607 A.addPatchset()
608 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
609 A.subject, B.data['id'])
610 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
611 self.waitUntilSettled()
612
613 # Dependency cycle injected so zuul should not have reported again on A
614 self.assertEqual(A.reported, 1)
615
616 # Now if we update B to remove the depends-on, everything
617 # should be okay. B; A->B
618
619 B.addPatchset()
620 B.data['commitMessage'] = '%s\n' % (B.subject,)
621 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
622 self.waitUntilSettled()
623
624 # Cycle was removed so now zuul should have reported again on A
625 self.assertEqual(A.reported, 2)
626
627 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(2))
628 self.waitUntilSettled()
629 self.assertEqual(B.reported, 2)