The Gatekeeper, or a project gating system
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

633 lines
24 KiB

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