blob: 6276569d86aa354dd9b225d81b382719e2bb437d [file] [log] [blame]
James E. Blairb0fcae42012-07-17 11:12:10 -07001#!/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
James E. Blairb0fcae42012-07-17 11:12:10 -070017import json
Monty Taylorbc758832013-06-17 17:22:42 -040018import logging
19import os
James E. Blairb0fcae42012-07-17 11:12:10 -070020import re
James E. Blair4886cc12012-07-18 15:39:41 -070021import shutil
Monty Taylorbc758832013-06-17 17:22:42 -040022import time
James E. Blair1843a552013-07-03 14:19:52 -070023import urllib
Monty Taylorbc758832013-06-17 17:22:42 -040024import urllib2
Maru Newby3fe5f852015-01-13 04:22:14 +000025import yaml
Monty Taylorbc758832013-06-17 17:22:42 -040026
James E. Blair4886cc12012-07-18 15:39:41 -070027import git
Monty Taylorbc758832013-06-17 17:22:42 -040028import testtools
James E. Blairb0fcae42012-07-17 11:12:10 -070029
Maru Newby3fe5f852015-01-13 04:22:14 +000030import zuul.change_matcher
James E. Blairb0fcae42012-07-17 11:12:10 -070031import zuul.scheduler
James E. Blairad28e912013-11-27 10:43:22 -080032import zuul.rpcclient
Joshua Hesketh1879cf72013-08-19 14:13:15 +100033import zuul.reporter.gerrit
Joshua Hesketh5fea8672013-08-19 17:32:01 +100034import zuul.reporter.smtp
James E. Blairb0fcae42012-07-17 11:12:10 -070035
Maru Newby3fe5f852015-01-13 04:22:14 +000036from tests.base import (
37 BaseTestCase,
38 ZuulTestCase,
39 repack_repo,
40)
James E. Blairb0fcae42012-07-17 11:12:10 -070041
James E. Blair1f4c2bb2013-04-26 08:40:46 -070042logging.basicConfig(level=logging.DEBUG,
43 format='%(asctime)s %(name)-32s '
44 '%(levelname)-8s %(message)s')
James E. Blairb0fcae42012-07-17 11:12:10 -070045
46
Maru Newby3fe5f852015-01-13 04:22:14 +000047class TestSchedulerConfigParsing(BaseTestCase):
48
49 def test_parse_skip_if(self):
50 job_yaml = """
51jobs:
52 - name: job_name
53 skip-if:
54 - project: ^project_name$
55 branch: ^stable/icehouse$
56 all-files-match-any:
57 - ^filename$
58 - project: ^project2_name$
59 all-files-match-any:
60 - ^filename2$
61 """.strip()
62 data = yaml.load(job_yaml)
63 config_job = data.get('jobs')[0]
64 sched = zuul.scheduler.Scheduler()
65 cm = zuul.change_matcher
66 expected = cm.MatchAny([
67 cm.MatchAll([
68 cm.ProjectMatcher('^project_name$'),
69 cm.BranchMatcher('^stable/icehouse$'),
70 cm.MatchAllFiles([cm.FileMatcher('^filename$')]),
71 ]),
72 cm.MatchAll([
73 cm.ProjectMatcher('^project2_name$'),
74 cm.MatchAllFiles([cm.FileMatcher('^filename2$')]),
75 ]),
76 ])
77 matcher = sched._parseSkipIf(config_job)
78 self.assertEqual(expected, matcher)
79
80
Clark Boylanb640e052014-04-03 16:41:46 -070081class TestScheduler(ZuulTestCase):
Antoine Mussobd86a312014-01-08 14:51:33 +010082
James E. Blairb0fcae42012-07-17 11:12:10 -070083 def test_jobs_launched(self):
84 "Test that jobs are launched and a change is merged"
James E. Blair1f4c2bb2013-04-26 08:40:46 -070085
James E. Blairb0fcae42012-07-17 11:12:10 -070086 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
James E. Blair8c803f82012-07-31 16:25:42 -070087 A.addApproval('CRVW', 2)
James E. Blairb0fcae42012-07-17 11:12:10 -070088 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
89 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -040090 self.assertEqual(self.getJobFromHistory('project-merge').result,
91 'SUCCESS')
92 self.assertEqual(self.getJobFromHistory('project-test1').result,
93 'SUCCESS')
94 self.assertEqual(self.getJobFromHistory('project-test2').result,
95 'SUCCESS')
96 self.assertEqual(A.data['status'], 'MERGED')
97 self.assertEqual(A.reported, 2)
James E. Blairb0fcae42012-07-17 11:12:10 -070098
James E. Blair66eeebf2013-07-27 17:44:32 -070099 self.assertReportedStat('gerrit.event.comment-added', value='1|c')
100 self.assertReportedStat('zuul.pipeline.gate.current_changes',
101 value='1|g')
102 self.assertReportedStat('zuul.pipeline.gate.job.project-merge.SUCCESS',
103 kind='ms')
104 self.assertReportedStat('zuul.pipeline.gate.job.project-merge.SUCCESS',
105 value='1|c')
106 self.assertReportedStat('zuul.pipeline.gate.resident_time', kind='ms')
107 self.assertReportedStat('zuul.pipeline.gate.total_changes',
108 value='1|c')
James E. Blair412e5582013-04-22 15:50:12 -0700109 self.assertReportedStat(
James E. Blair66eeebf2013-07-27 17:44:32 -0700110 'zuul.pipeline.gate.org.project.resident_time', kind='ms')
James E. Blair412e5582013-04-22 15:50:12 -0700111 self.assertReportedStat(
James E. Blair66eeebf2013-07-27 17:44:32 -0700112 'zuul.pipeline.gate.org.project.total_changes', value='1|c')
James E. Blair412e5582013-04-22 15:50:12 -0700113
James E. Blair5821bd92015-09-16 08:48:15 -0700114 for build in self.builds:
115 self.assertEqual(build.parameters['ZUUL_VOTING'], '1')
116
James E. Blair3cb10702013-08-24 08:56:03 -0700117 def test_initial_pipeline_gauges(self):
118 "Test that each pipeline reported its length on start"
119 pipeline_names = self.sched.layout.pipelines.keys()
120 self.assertNotEqual(len(pipeline_names), 0)
121 for name in pipeline_names:
122 self.assertReportedStat('zuul.pipeline.%s.current_changes' % name,
123 value='0|g')
124
James E. Blair42f74822013-05-14 15:18:03 -0700125 def test_duplicate_pipelines(self):
126 "Test that a change matching multiple pipelines works"
James E. Blair1b4d9722013-05-21 10:32:04 -0700127
James E. Blair42f74822013-05-14 15:18:03 -0700128 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
129 self.fake_gerrit.addEvent(A.getChangeRestoredEvent())
130 self.waitUntilSettled()
James E. Blair42f74822013-05-14 15:18:03 -0700131
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400132 self.assertEqual(len(self.history), 2)
Monty Taylor6bef8ef2013-06-02 08:17:12 -0400133 self.history[0].name == 'project-test1'
134 self.history[1].name == 'project-test1'
James E. Blair42f74822013-05-14 15:18:03 -0700135
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400136 self.assertEqual(len(A.messages), 2)
James E. Blair42f74822013-05-14 15:18:03 -0700137 if 'dup1/project-test1' in A.messages[0]:
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400138 self.assertIn('dup1/project-test1', A.messages[0])
139 self.assertNotIn('dup2/project-test1', A.messages[0])
140 self.assertNotIn('dup1/project-test1', A.messages[1])
141 self.assertIn('dup2/project-test1', A.messages[1])
James E. Blair42f74822013-05-14 15:18:03 -0700142 else:
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400143 self.assertIn('dup1/project-test1', A.messages[1])
144 self.assertNotIn('dup2/project-test1', A.messages[1])
145 self.assertNotIn('dup1/project-test1', A.messages[0])
146 self.assertIn('dup2/project-test1', A.messages[0])
James E. Blair42f74822013-05-14 15:18:03 -0700147
James E. Blairb0fcae42012-07-17 11:12:10 -0700148 def test_parallel_changes(self):
149 "Test that changes are tested in parallel and merged in series"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700150
151 self.worker.hold_jobs_in_build = True
James E. Blairb0fcae42012-07-17 11:12:10 -0700152 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
153 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
154 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
James E. Blair8c803f82012-07-31 16:25:42 -0700155 A.addApproval('CRVW', 2)
156 B.addApproval('CRVW', 2)
157 C.addApproval('CRVW', 2)
James E. Blairb0fcae42012-07-17 11:12:10 -0700158
159 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
160 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
161 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
162
163 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400164 self.assertEqual(len(self.builds), 1)
165 self.assertEqual(self.builds[0].name, 'project-merge')
166 self.assertTrue(self.job_has_changes(self.builds[0], A))
James E. Blairb0fcae42012-07-17 11:12:10 -0700167
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700168 self.worker.release('.*-merge')
James E. Blairb0fcae42012-07-17 11:12:10 -0700169 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400170 self.assertEqual(len(self.builds), 3)
171 self.assertEqual(self.builds[0].name, 'project-test1')
172 self.assertTrue(self.job_has_changes(self.builds[0], A))
173 self.assertEqual(self.builds[1].name, 'project-test2')
174 self.assertTrue(self.job_has_changes(self.builds[1], A))
175 self.assertEqual(self.builds[2].name, 'project-merge')
176 self.assertTrue(self.job_has_changes(self.builds[2], A, B))
James E. Blairb0fcae42012-07-17 11:12:10 -0700177
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700178 self.worker.release('.*-merge')
James E. Blairb0fcae42012-07-17 11:12:10 -0700179 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400180 self.assertEqual(len(self.builds), 5)
181 self.assertEqual(self.builds[0].name, 'project-test1')
182 self.assertTrue(self.job_has_changes(self.builds[0], A))
183 self.assertEqual(self.builds[1].name, 'project-test2')
184 self.assertTrue(self.job_has_changes(self.builds[1], A))
James E. Blairb0fcae42012-07-17 11:12:10 -0700185
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400186 self.assertEqual(self.builds[2].name, 'project-test1')
187 self.assertTrue(self.job_has_changes(self.builds[2], A, B))
188 self.assertEqual(self.builds[3].name, 'project-test2')
189 self.assertTrue(self.job_has_changes(self.builds[3], A, B))
James E. Blairb0fcae42012-07-17 11:12:10 -0700190
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400191 self.assertEqual(self.builds[4].name, 'project-merge')
192 self.assertTrue(self.job_has_changes(self.builds[4], A, B, C))
James E. Blairb0fcae42012-07-17 11:12:10 -0700193
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700194 self.worker.release('.*-merge')
James E. Blairb0fcae42012-07-17 11:12:10 -0700195 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400196 self.assertEqual(len(self.builds), 6)
197 self.assertEqual(self.builds[0].name, 'project-test1')
198 self.assertTrue(self.job_has_changes(self.builds[0], A))
199 self.assertEqual(self.builds[1].name, 'project-test2')
200 self.assertTrue(self.job_has_changes(self.builds[1], A))
James E. Blairb0fcae42012-07-17 11:12:10 -0700201
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400202 self.assertEqual(self.builds[2].name, 'project-test1')
203 self.assertTrue(self.job_has_changes(self.builds[2], A, B))
204 self.assertEqual(self.builds[3].name, 'project-test2')
205 self.assertTrue(self.job_has_changes(self.builds[3], A, B))
James E. Blairb0fcae42012-07-17 11:12:10 -0700206
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400207 self.assertEqual(self.builds[4].name, 'project-test1')
208 self.assertTrue(self.job_has_changes(self.builds[4], A, B, C))
209 self.assertEqual(self.builds[5].name, 'project-test2')
210 self.assertTrue(self.job_has_changes(self.builds[5], A, B, C))
James E. Blairb0fcae42012-07-17 11:12:10 -0700211
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700212 self.worker.hold_jobs_in_build = False
213 self.worker.release()
James E. Blairb0fcae42012-07-17 11:12:10 -0700214 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400215 self.assertEqual(len(self.builds), 0)
James E. Blairb0fcae42012-07-17 11:12:10 -0700216
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400217 self.assertEqual(len(self.history), 9)
218 self.assertEqual(A.data['status'], 'MERGED')
219 self.assertEqual(B.data['status'], 'MERGED')
220 self.assertEqual(C.data['status'], 'MERGED')
221 self.assertEqual(A.reported, 2)
222 self.assertEqual(B.reported, 2)
223 self.assertEqual(C.reported, 2)
James E. Blairb02a3bb2012-07-30 17:49:55 -0700224
225 def test_failed_changes(self):
226 "Test that a change behind a failed change is retested"
James E. Blaire2819012013-06-28 17:17:26 -0400227 self.worker.hold_jobs_in_build = True
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700228
James E. Blairb02a3bb2012-07-30 17:49:55 -0700229 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
230 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
James E. Blair8c803f82012-07-31 16:25:42 -0700231 A.addApproval('CRVW', 2)
232 B.addApproval('CRVW', 2)
James E. Blairb02a3bb2012-07-30 17:49:55 -0700233
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700234 self.worker.addFailTest('project-test1', A)
James E. Blairb02a3bb2012-07-30 17:49:55 -0700235
James E. Blaire2819012013-06-28 17:17:26 -0400236 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
237 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
James E. Blairb02a3bb2012-07-30 17:49:55 -0700238 self.waitUntilSettled()
James E. Blaire2819012013-06-28 17:17:26 -0400239
240 self.worker.release('.*-merge')
241 self.waitUntilSettled()
242
243 self.worker.hold_jobs_in_build = False
244 self.worker.release()
245
246 self.waitUntilSettled()
247 # It's certain that the merge job for change 2 will run, but
248 # the test1 and test2 jobs may or may not run.
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400249 self.assertTrue(len(self.history) > 6)
250 self.assertEqual(A.data['status'], 'NEW')
251 self.assertEqual(B.data['status'], 'MERGED')
252 self.assertEqual(A.reported, 2)
253 self.assertEqual(B.reported, 2)
James E. Blairb02a3bb2012-07-30 17:49:55 -0700254
255 def test_independent_queues(self):
256 "Test that changes end up in the right queues"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700257
258 self.worker.hold_jobs_in_build = True
Zhongyue Luo5d556072012-09-21 02:00:47 +0900259 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
James E. Blairb02a3bb2012-07-30 17:49:55 -0700260 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
261 C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
James E. Blair8c803f82012-07-31 16:25:42 -0700262 A.addApproval('CRVW', 2)
263 B.addApproval('CRVW', 2)
264 C.addApproval('CRVW', 2)
James E. Blairb02a3bb2012-07-30 17:49:55 -0700265
266 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
267 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
268 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
269
James E. Blairb02a3bb2012-07-30 17:49:55 -0700270 self.waitUntilSettled()
271
272 # There should be one merge job at the head of each queue running
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400273 self.assertEqual(len(self.builds), 2)
274 self.assertEqual(self.builds[0].name, 'project-merge')
275 self.assertTrue(self.job_has_changes(self.builds[0], A))
276 self.assertEqual(self.builds[1].name, 'project1-merge')
277 self.assertTrue(self.job_has_changes(self.builds[1], B))
James E. Blairb02a3bb2012-07-30 17:49:55 -0700278
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700279 # Release the current merge builds
280 self.worker.release('.*-merge')
James E. Blairb02a3bb2012-07-30 17:49:55 -0700281 self.waitUntilSettled()
282 # Release the merge job for project2 which is behind project1
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700283 self.worker.release('.*-merge')
James E. Blairb02a3bb2012-07-30 17:49:55 -0700284 self.waitUntilSettled()
285
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700286 # All the test builds should be running:
James E. Blairb02a3bb2012-07-30 17:49:55 -0700287 # project1 (3) + project2 (3) + project (2) = 8
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400288 self.assertEqual(len(self.builds), 8)
James E. Blairb02a3bb2012-07-30 17:49:55 -0700289
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700290 self.worker.release()
James E. Blairb02a3bb2012-07-30 17:49:55 -0700291 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400292 self.assertEqual(len(self.builds), 0)
James E. Blairb02a3bb2012-07-30 17:49:55 -0700293
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400294 self.assertEqual(len(self.history), 11)
295 self.assertEqual(A.data['status'], 'MERGED')
296 self.assertEqual(B.data['status'], 'MERGED')
297 self.assertEqual(C.data['status'], 'MERGED')
298 self.assertEqual(A.reported, 2)
299 self.assertEqual(B.reported, 2)
300 self.assertEqual(C.reported, 2)
James E. Blaird466dc42012-07-31 10:42:56 -0700301
302 def test_failed_change_at_head(self):
303 "Test that if a change at the head fails, jobs behind it are canceled"
James E. Blaird466dc42012-07-31 10:42:56 -0700304
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700305 self.worker.hold_jobs_in_build = True
James E. Blaird466dc42012-07-31 10:42:56 -0700306 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
307 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
308 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
James E. Blair8c803f82012-07-31 16:25:42 -0700309 A.addApproval('CRVW', 2)
310 B.addApproval('CRVW', 2)
311 C.addApproval('CRVW', 2)
James E. Blaird466dc42012-07-31 10:42:56 -0700312
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700313 self.worker.addFailTest('project-test1', A)
James E. Blaird466dc42012-07-31 10:42:56 -0700314
315 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
316 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
317 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
318
319 self.waitUntilSettled()
James E. Blaird466dc42012-07-31 10:42:56 -0700320
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400321 self.assertEqual(len(self.builds), 1)
322 self.assertEqual(self.builds[0].name, 'project-merge')
323 self.assertTrue(self.job_has_changes(self.builds[0], A))
James E. Blaird466dc42012-07-31 10:42:56 -0700324
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700325 self.worker.release('.*-merge')
James E. Blaird466dc42012-07-31 10:42:56 -0700326 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700327 self.worker.release('.*-merge')
James E. Blaird466dc42012-07-31 10:42:56 -0700328 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700329 self.worker.release('.*-merge')
James E. Blaird466dc42012-07-31 10:42:56 -0700330 self.waitUntilSettled()
331
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400332 self.assertEqual(len(self.builds), 6)
333 self.assertEqual(self.builds[0].name, 'project-test1')
334 self.assertEqual(self.builds[1].name, 'project-test2')
335 self.assertEqual(self.builds[2].name, 'project-test1')
336 self.assertEqual(self.builds[3].name, 'project-test2')
337 self.assertEqual(self.builds[4].name, 'project-test1')
338 self.assertEqual(self.builds[5].name, 'project-test2')
James E. Blaird466dc42012-07-31 10:42:56 -0700339
Monty Taylor6bef8ef2013-06-02 08:17:12 -0400340 self.release(self.builds[0])
James E. Blaird466dc42012-07-31 10:42:56 -0700341 self.waitUntilSettled()
342
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400343 # project-test2, project-merge for B
344 self.assertEqual(len(self.builds), 2)
345 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 4)
James E. Blaird466dc42012-07-31 10:42:56 -0700346
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700347 self.worker.hold_jobs_in_build = False
348 self.worker.release()
James E. Blaird466dc42012-07-31 10:42:56 -0700349 self.waitUntilSettled()
350
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400351 self.assertEqual(len(self.builds), 0)
352 self.assertEqual(len(self.history), 15)
353 self.assertEqual(A.data['status'], 'NEW')
354 self.assertEqual(B.data['status'], 'MERGED')
355 self.assertEqual(C.data['status'], 'MERGED')
356 self.assertEqual(A.reported, 2)
357 self.assertEqual(B.reported, 2)
358 self.assertEqual(C.reported, 2)
James E. Blaird466dc42012-07-31 10:42:56 -0700359
James E. Blair0aac4872013-08-23 14:02:38 -0700360 def test_failed_change_in_middle(self):
361 "Test a failed change in the middle of the queue"
362
363 self.worker.hold_jobs_in_build = True
364 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
365 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
366 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
367 A.addApproval('CRVW', 2)
368 B.addApproval('CRVW', 2)
369 C.addApproval('CRVW', 2)
370
371 self.worker.addFailTest('project-test1', B)
372
373 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
374 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
375 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
376
377 self.waitUntilSettled()
378
379 self.worker.release('.*-merge')
380 self.waitUntilSettled()
381 self.worker.release('.*-merge')
382 self.waitUntilSettled()
383 self.worker.release('.*-merge')
384 self.waitUntilSettled()
385
386 self.assertEqual(len(self.builds), 6)
387 self.assertEqual(self.builds[0].name, 'project-test1')
388 self.assertEqual(self.builds[1].name, 'project-test2')
389 self.assertEqual(self.builds[2].name, 'project-test1')
390 self.assertEqual(self.builds[3].name, 'project-test2')
391 self.assertEqual(self.builds[4].name, 'project-test1')
392 self.assertEqual(self.builds[5].name, 'project-test2')
393
394 self.release(self.builds[2])
395 self.waitUntilSettled()
396
James E. Blair972e3c72013-08-29 12:04:55 -0700397 # project-test1 and project-test2 for A
398 # project-test2 for B
399 # project-merge for C (without B)
400 self.assertEqual(len(self.builds), 4)
James E. Blair0aac4872013-08-23 14:02:38 -0700401 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 2)
402
James E. Blair972e3c72013-08-29 12:04:55 -0700403 self.worker.release('.*-merge')
404 self.waitUntilSettled()
405
406 # project-test1 and project-test2 for A
407 # project-test2 for B
408 # project-test1 and project-test2 for C
409 self.assertEqual(len(self.builds), 5)
410
James E. Blair0aac4872013-08-23 14:02:38 -0700411 items = self.sched.layout.pipelines['gate'].getAllItems()
412 builds = items[0].current_build_set.getBuilds()
413 self.assertEqual(self.countJobResults(builds, 'SUCCESS'), 1)
414 self.assertEqual(self.countJobResults(builds, None), 2)
415 builds = items[1].current_build_set.getBuilds()
416 self.assertEqual(self.countJobResults(builds, 'SUCCESS'), 1)
417 self.assertEqual(self.countJobResults(builds, 'FAILURE'), 1)
418 self.assertEqual(self.countJobResults(builds, None), 1)
419 builds = items[2].current_build_set.getBuilds()
420 self.assertEqual(self.countJobResults(builds, 'SUCCESS'), 1)
James E. Blair972e3c72013-08-29 12:04:55 -0700421 self.assertEqual(self.countJobResults(builds, None), 2)
James E. Blair0aac4872013-08-23 14:02:38 -0700422
423 self.worker.hold_jobs_in_build = False
424 self.worker.release()
425 self.waitUntilSettled()
426
427 self.assertEqual(len(self.builds), 0)
428 self.assertEqual(len(self.history), 12)
429 self.assertEqual(A.data['status'], 'MERGED')
430 self.assertEqual(B.data['status'], 'NEW')
431 self.assertEqual(C.data['status'], 'MERGED')
432 self.assertEqual(A.reported, 2)
433 self.assertEqual(B.reported, 2)
434 self.assertEqual(C.reported, 2)
435
James E. Blaird466dc42012-07-31 10:42:56 -0700436 def test_failed_change_at_head_with_queue(self):
437 "Test that if a change at the head fails, queued jobs are canceled"
James E. Blaird466dc42012-07-31 10:42:56 -0700438
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700439 self.gearman_server.hold_jobs_in_queue = True
James E. Blaird466dc42012-07-31 10:42:56 -0700440 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
441 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
442 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
James E. Blair8c803f82012-07-31 16:25:42 -0700443 A.addApproval('CRVW', 2)
444 B.addApproval('CRVW', 2)
445 C.addApproval('CRVW', 2)
James E. Blaird466dc42012-07-31 10:42:56 -0700446
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700447 self.worker.addFailTest('project-test1', A)
James E. Blaird466dc42012-07-31 10:42:56 -0700448
449 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
450 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
451 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
452
453 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -0700454 queue = self.gearman_server.getQueue()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400455 self.assertEqual(len(self.builds), 0)
456 self.assertEqual(len(queue), 1)
457 self.assertEqual(queue[0].name, 'build:project-merge')
458 self.assertTrue(self.job_has_changes(queue[0], A))
James E. Blaird466dc42012-07-31 10:42:56 -0700459
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700460 self.gearman_server.release('.*-merge')
James E. Blaird466dc42012-07-31 10:42:56 -0700461 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700462 self.gearman_server.release('.*-merge')
James E. Blaird466dc42012-07-31 10:42:56 -0700463 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700464 self.gearman_server.release('.*-merge')
James E. Blaird466dc42012-07-31 10:42:56 -0700465 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -0700466 queue = self.gearman_server.getQueue()
James E. Blaird466dc42012-07-31 10:42:56 -0700467
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400468 self.assertEqual(len(self.builds), 0)
469 self.assertEqual(len(queue), 6)
470 self.assertEqual(queue[0].name, 'build:project-test1')
471 self.assertEqual(queue[1].name, 'build:project-test2')
472 self.assertEqual(queue[2].name, 'build:project-test1')
473 self.assertEqual(queue[3].name, 'build:project-test2')
474 self.assertEqual(queue[4].name, 'build:project-test1')
475 self.assertEqual(queue[5].name, 'build:project-test2')
James E. Blaird466dc42012-07-31 10:42:56 -0700476
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700477 self.release(queue[0])
James E. Blaird466dc42012-07-31 10:42:56 -0700478 self.waitUntilSettled()
479
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400480 self.assertEqual(len(self.builds), 0)
James E. Blair701c5b42013-06-06 09:34:59 -0700481 queue = self.gearman_server.getQueue()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400482 self.assertEqual(len(queue), 2) # project-test2, project-merge for B
483 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 0)
James E. Blaird466dc42012-07-31 10:42:56 -0700484
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700485 self.gearman_server.hold_jobs_in_queue = False
486 self.gearman_server.release()
James E. Blaird466dc42012-07-31 10:42:56 -0700487 self.waitUntilSettled()
488
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400489 self.assertEqual(len(self.builds), 0)
490 self.assertEqual(len(self.history), 11)
491 self.assertEqual(A.data['status'], 'NEW')
492 self.assertEqual(B.data['status'], 'MERGED')
493 self.assertEqual(C.data['status'], 'MERGED')
494 self.assertEqual(A.reported, 2)
495 self.assertEqual(B.reported, 2)
496 self.assertEqual(C.reported, 2)
James E. Blair8c803f82012-07-31 16:25:42 -0700497
James E. Blairfef71632013-09-23 11:15:47 -0700498 def test_two_failed_changes_at_head(self):
499 "Test that changes are reparented correctly if 2 fail at head"
500
501 self.worker.hold_jobs_in_build = True
502 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
503 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
504 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
505 A.addApproval('CRVW', 2)
506 B.addApproval('CRVW', 2)
507 C.addApproval('CRVW', 2)
508
509 self.worker.addFailTest('project-test1', A)
510 self.worker.addFailTest('project-test1', B)
511
512 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
513 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
514 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
515 self.waitUntilSettled()
516
517 self.worker.release('.*-merge')
518 self.waitUntilSettled()
519 self.worker.release('.*-merge')
520 self.waitUntilSettled()
521 self.worker.release('.*-merge')
522 self.waitUntilSettled()
523
524 self.assertEqual(len(self.builds), 6)
525 self.assertEqual(self.builds[0].name, 'project-test1')
526 self.assertEqual(self.builds[1].name, 'project-test2')
527 self.assertEqual(self.builds[2].name, 'project-test1')
528 self.assertEqual(self.builds[3].name, 'project-test2')
529 self.assertEqual(self.builds[4].name, 'project-test1')
530 self.assertEqual(self.builds[5].name, 'project-test2')
531
532 self.assertTrue(self.job_has_changes(self.builds[0], A))
533 self.assertTrue(self.job_has_changes(self.builds[2], A))
534 self.assertTrue(self.job_has_changes(self.builds[2], B))
535 self.assertTrue(self.job_has_changes(self.builds[4], A))
536 self.assertTrue(self.job_has_changes(self.builds[4], B))
537 self.assertTrue(self.job_has_changes(self.builds[4], C))
538
539 # Fail change B first
540 self.release(self.builds[2])
541 self.waitUntilSettled()
542
543 # restart of C after B failure
544 self.worker.release('.*-merge')
545 self.waitUntilSettled()
546
547 self.assertEqual(len(self.builds), 5)
548 self.assertEqual(self.builds[0].name, 'project-test1')
549 self.assertEqual(self.builds[1].name, 'project-test2')
550 self.assertEqual(self.builds[2].name, 'project-test2')
551 self.assertEqual(self.builds[3].name, 'project-test1')
552 self.assertEqual(self.builds[4].name, 'project-test2')
553
554 self.assertTrue(self.job_has_changes(self.builds[1], A))
555 self.assertTrue(self.job_has_changes(self.builds[2], A))
556 self.assertTrue(self.job_has_changes(self.builds[2], B))
557 self.assertTrue(self.job_has_changes(self.builds[4], A))
558 self.assertFalse(self.job_has_changes(self.builds[4], B))
559 self.assertTrue(self.job_has_changes(self.builds[4], C))
560
561 # Finish running all passing jobs for change A
562 self.release(self.builds[1])
563 self.waitUntilSettled()
564 # Fail and report change A
565 self.release(self.builds[0])
566 self.waitUntilSettled()
567
568 # restart of B,C after A failure
569 self.worker.release('.*-merge')
570 self.waitUntilSettled()
571 self.worker.release('.*-merge')
572 self.waitUntilSettled()
573
574 self.assertEqual(len(self.builds), 4)
575 self.assertEqual(self.builds[0].name, 'project-test1') # B
576 self.assertEqual(self.builds[1].name, 'project-test2') # B
577 self.assertEqual(self.builds[2].name, 'project-test1') # C
578 self.assertEqual(self.builds[3].name, 'project-test2') # C
579
580 self.assertFalse(self.job_has_changes(self.builds[1], A))
581 self.assertTrue(self.job_has_changes(self.builds[1], B))
582 self.assertFalse(self.job_has_changes(self.builds[1], C))
583
584 self.assertFalse(self.job_has_changes(self.builds[2], A))
585 # After A failed and B and C restarted, B should be back in
586 # C's tests because it has not failed yet.
587 self.assertTrue(self.job_has_changes(self.builds[2], B))
588 self.assertTrue(self.job_has_changes(self.builds[2], C))
589
590 self.worker.hold_jobs_in_build = False
591 self.worker.release()
592 self.waitUntilSettled()
593
594 self.assertEqual(len(self.builds), 0)
595 self.assertEqual(len(self.history), 21)
596 self.assertEqual(A.data['status'], 'NEW')
597 self.assertEqual(B.data['status'], 'NEW')
598 self.assertEqual(C.data['status'], 'MERGED')
599 self.assertEqual(A.reported, 2)
600 self.assertEqual(B.reported, 2)
601 self.assertEqual(C.reported, 2)
602
James E. Blair8c803f82012-07-31 16:25:42 -0700603 def test_patch_order(self):
604 "Test that dependent patches are tested in the right order"
605 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
606 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
607 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
608 A.addApproval('CRVW', 2)
609 B.addApproval('CRVW', 2)
610 C.addApproval('CRVW', 2)
611
612 M2 = self.fake_gerrit.addFakeChange('org/project', 'master', 'M2')
613 M1 = self.fake_gerrit.addFakeChange('org/project', 'master', 'M1')
614 M2.setMerged()
615 M1.setMerged()
616
617 # C -> B -> A -> M1 -> M2
618 # M2 is here to make sure it is never queried. If it is, it
619 # means zuul is walking down the entire history of merged
620 # changes.
621
622 C.setDependsOn(B, 1)
623 B.setDependsOn(A, 1)
624 A.setDependsOn(M1, 1)
625 M1.setDependsOn(M2, 1)
626
627 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
628
629 self.waitUntilSettled()
630
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400631 self.assertEqual(A.data['status'], 'NEW')
632 self.assertEqual(B.data['status'], 'NEW')
633 self.assertEqual(C.data['status'], 'NEW')
James E. Blair8c803f82012-07-31 16:25:42 -0700634
635 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
636 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
637
638 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400639 self.assertEqual(M2.queried, 0)
640 self.assertEqual(A.data['status'], 'MERGED')
641 self.assertEqual(B.data['status'], 'MERGED')
642 self.assertEqual(C.data['status'], 'MERGED')
643 self.assertEqual(A.reported, 2)
644 self.assertEqual(B.reported, 2)
645 self.assertEqual(C.reported, 2)
James E. Blair8c803f82012-07-31 16:25:42 -0700646
James E. Blair063672f2015-01-29 13:09:12 -0800647 def test_needed_changes_enqueue(self):
648 "Test that a needed change is enqueued ahead"
649 # A Given a git tree like this, if we enqueue
650 # / \ change C, we should walk up and down the tree
651 # B G and enqueue changes in the order ABCDEFG.
652 # /|\ This is also the order that you would get if
653 # *C E F you enqueued changes in the order ABCDEFG, so
654 # / the ordering is stable across re-enqueue events.
655 # D
656
657 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
658 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
659 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
660 D = self.fake_gerrit.addFakeChange('org/project', 'master', 'D')
661 E = self.fake_gerrit.addFakeChange('org/project', 'master', 'E')
662 F = self.fake_gerrit.addFakeChange('org/project', 'master', 'F')
663 G = self.fake_gerrit.addFakeChange('org/project', 'master', 'G')
664 B.setDependsOn(A, 1)
665 C.setDependsOn(B, 1)
666 D.setDependsOn(C, 1)
667 E.setDependsOn(B, 1)
668 F.setDependsOn(B, 1)
669 G.setDependsOn(A, 1)
670
671 A.addApproval('CRVW', 2)
672 B.addApproval('CRVW', 2)
673 C.addApproval('CRVW', 2)
674 D.addApproval('CRVW', 2)
675 E.addApproval('CRVW', 2)
676 F.addApproval('CRVW', 2)
677 G.addApproval('CRVW', 2)
678 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
679
680 self.waitUntilSettled()
681
682 self.assertEqual(A.data['status'], 'NEW')
683 self.assertEqual(B.data['status'], 'NEW')
684 self.assertEqual(C.data['status'], 'NEW')
685 self.assertEqual(D.data['status'], 'NEW')
686 self.assertEqual(E.data['status'], 'NEW')
687 self.assertEqual(F.data['status'], 'NEW')
688 self.assertEqual(G.data['status'], 'NEW')
689
690 # We're about to add approvals to changes without adding the
691 # triggering events to Zuul, so that we can be sure that it is
692 # enqueing the changes based on dependencies, not because of
693 # triggering events. Since it will have the changes cached
694 # already (without approvals), we need to clear the cache
695 # first.
696 source = self.sched.layout.pipelines['gate'].source
697 source.maintainCache([])
698
699 self.worker.hold_jobs_in_build = True
700 A.addApproval('APRV', 1)
701 B.addApproval('APRV', 1)
702 D.addApproval('APRV', 1)
703 E.addApproval('APRV', 1)
704 F.addApproval('APRV', 1)
705 G.addApproval('APRV', 1)
706 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
707
708 for x in range(8):
709 self.worker.release('.*-merge')
710 self.waitUntilSettled()
711 self.worker.hold_jobs_in_build = False
712 self.worker.release()
713 self.waitUntilSettled()
714
715 self.assertEqual(A.data['status'], 'MERGED')
716 self.assertEqual(B.data['status'], 'MERGED')
717 self.assertEqual(C.data['status'], 'MERGED')
718 self.assertEqual(D.data['status'], 'MERGED')
719 self.assertEqual(E.data['status'], 'MERGED')
720 self.assertEqual(F.data['status'], 'MERGED')
721 self.assertEqual(G.data['status'], 'MERGED')
722 self.assertEqual(A.reported, 2)
723 self.assertEqual(B.reported, 2)
724 self.assertEqual(C.reported, 2)
725 self.assertEqual(D.reported, 2)
726 self.assertEqual(E.reported, 2)
727 self.assertEqual(F.reported, 2)
728 self.assertEqual(G.reported, 2)
729 self.assertEqual(self.history[6].changes,
730 '1,1 2,1 3,1 4,1 5,1 6,1 7,1')
731
James E. Blair0e933c52013-07-11 10:18:52 -0700732 def test_trigger_cache(self):
733 "Test that the trigger cache operates correctly"
734 self.worker.hold_jobs_in_build = True
735
736 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
737 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
738 X = self.fake_gerrit.addFakeChange('org/project', 'master', 'X')
739 A.addApproval('CRVW', 2)
740 B.addApproval('CRVW', 2)
741
742 M1 = self.fake_gerrit.addFakeChange('org/project', 'master', 'M1')
743 M1.setMerged()
744
745 B.setDependsOn(A, 1)
746 A.setDependsOn(M1, 1)
747
748 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
749 self.fake_gerrit.addEvent(X.getPatchsetCreatedEvent(1))
750
751 self.waitUntilSettled()
752
753 for build in self.builds:
754 if build.parameters['ZUUL_PIPELINE'] == 'check':
755 build.release()
756 self.waitUntilSettled()
757 for build in self.builds:
758 if build.parameters['ZUUL_PIPELINE'] == 'check':
759 build.release()
760 self.waitUntilSettled()
761
762 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
763 self.waitUntilSettled()
764
Antoine Mussof0506fa2014-06-03 15:03:38 +0200765 self.log.debug("len %s" % self.gerrit._change_cache.keys())
James E. Blair0e933c52013-07-11 10:18:52 -0700766 # there should still be changes in the cache
James E. Blair6c358e72013-07-29 17:06:47 -0700767 self.assertNotEqual(len(self.gerrit._change_cache.keys()), 0)
James E. Blair0e933c52013-07-11 10:18:52 -0700768
769 self.worker.hold_jobs_in_build = False
770 self.worker.release()
771 self.waitUntilSettled()
772
773 self.assertEqual(A.data['status'], 'MERGED')
774 self.assertEqual(B.data['status'], 'MERGED')
775 self.assertEqual(A.queried, 2) # Initial and isMerged
776 self.assertEqual(B.queried, 3) # Initial A, refresh from B, isMerged
777
James E. Blair8c803f82012-07-31 16:25:42 -0700778 def test_can_merge(self):
James E. Blair4886cc12012-07-18 15:39:41 -0700779 "Test whether a change is ready to merge"
James E. Blair8c803f82012-07-31 16:25:42 -0700780 # TODO: move to test_gerrit (this is a unit test!)
781 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
James E. Blairc0dedf82014-08-06 09:37:52 -0700782 source = self.sched.layout.pipelines['gate'].source
783 a = source._getChange(1, 2)
James E. Blaireff88162013-07-01 12:44:14 -0400784 mgr = self.sched.layout.pipelines['gate'].manager
James E. Blairc0dedf82014-08-06 09:37:52 -0700785 self.assertFalse(source.canMerge(a, mgr.getSubmitAllowNeeds()))
James E. Blair8c803f82012-07-31 16:25:42 -0700786
787 A.addApproval('CRVW', 2)
James E. Blairc0dedf82014-08-06 09:37:52 -0700788 a = source._getChange(1, 2, refresh=True)
789 self.assertFalse(source.canMerge(a, mgr.getSubmitAllowNeeds()))
James E. Blair8c803f82012-07-31 16:25:42 -0700790
791 A.addApproval('APRV', 1)
James E. Blairc0dedf82014-08-06 09:37:52 -0700792 a = source._getChange(1, 2, refresh=True)
793 self.assertTrue(source.canMerge(a, mgr.getSubmitAllowNeeds()))
794 source.maintainCache([])
James E. Blair4886cc12012-07-18 15:39:41 -0700795
796 def test_build_configuration(self):
797 "Test that zuul merges the right commits for testing"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700798
799 self.gearman_server.hold_jobs_in_queue = True
James E. Blair4886cc12012-07-18 15:39:41 -0700800 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
801 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
802 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
803 A.addApproval('CRVW', 2)
804 B.addApproval('CRVW', 2)
805 C.addApproval('CRVW', 2)
806 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
807 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
808 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
809 self.waitUntilSettled()
810
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700811 self.gearman_server.release('.*-merge')
James E. Blair4886cc12012-07-18 15:39:41 -0700812 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700813 self.gearman_server.release('.*-merge')
James E. Blair4886cc12012-07-18 15:39:41 -0700814 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700815 self.gearman_server.release('.*-merge')
James E. Blair4886cc12012-07-18 15:39:41 -0700816 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -0700817 queue = self.gearman_server.getQueue()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700818 ref = self.getParameter(queue[-1], 'ZUUL_REF')
819 self.gearman_server.hold_jobs_in_queue = False
820 self.gearman_server.release()
James E. Blair973721f2012-08-15 10:19:43 -0700821 self.waitUntilSettled()
James E. Blair4886cc12012-07-18 15:39:41 -0700822
Monty Taylorbc758832013-06-17 17:22:42 -0400823 path = os.path.join(self.git_root, "org/project")
James E. Blair4886cc12012-07-18 15:39:41 -0700824 repo = git.Repo(path)
825 repo_messages = [c.message.strip() for c in repo.iter_commits(ref)]
826 repo_messages.reverse()
James E. Blair4886cc12012-07-18 15:39:41 -0700827 correct_messages = ['initial commit', 'A-1', 'B-1', 'C-1']
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400828 self.assertEqual(repo_messages, correct_messages)
James E. Blair973721f2012-08-15 10:19:43 -0700829
830 def test_build_configuration_conflict(self):
831 "Test that merge conflicts are handled"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700832
833 self.gearman_server.hold_jobs_in_queue = True
James E. Blair6736beb2013-07-11 15:18:15 -0700834 A = self.fake_gerrit.addFakeChange('org/conflict-project',
835 'master', 'A')
James E. Blair973721f2012-08-15 10:19:43 -0700836 A.addPatchset(['conflict'])
James E. Blair6736beb2013-07-11 15:18:15 -0700837 B = self.fake_gerrit.addFakeChange('org/conflict-project',
838 'master', 'B')
James E. Blair973721f2012-08-15 10:19:43 -0700839 B.addPatchset(['conflict'])
James E. Blair6736beb2013-07-11 15:18:15 -0700840 C = self.fake_gerrit.addFakeChange('org/conflict-project',
841 'master', 'C')
James E. Blair973721f2012-08-15 10:19:43 -0700842 A.addApproval('CRVW', 2)
843 B.addApproval('CRVW', 2)
844 C.addApproval('CRVW', 2)
845 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
846 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
847 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
848 self.waitUntilSettled()
849
James E. Blair6736beb2013-07-11 15:18:15 -0700850 self.assertEqual(A.reported, 1)
851 self.assertEqual(B.reported, 1)
852 self.assertEqual(C.reported, 1)
853
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700854 self.gearman_server.release('.*-merge')
James E. Blair973721f2012-08-15 10:19:43 -0700855 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700856 self.gearman_server.release('.*-merge')
James E. Blair973721f2012-08-15 10:19:43 -0700857 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700858 self.gearman_server.release('.*-merge')
James E. Blair973721f2012-08-15 10:19:43 -0700859 self.waitUntilSettled()
James E. Blair972e3c72013-08-29 12:04:55 -0700860
861 self.assertEqual(len(self.history), 2) # A and C merge jobs
862
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700863 self.gearman_server.hold_jobs_in_queue = False
864 self.gearman_server.release()
James E. Blair973721f2012-08-15 10:19:43 -0700865 self.waitUntilSettled()
866
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400867 self.assertEqual(A.data['status'], 'MERGED')
868 self.assertEqual(B.data['status'], 'NEW')
869 self.assertEqual(C.data['status'], 'MERGED')
870 self.assertEqual(A.reported, 2)
871 self.assertEqual(B.reported, 2)
872 self.assertEqual(C.reported, 2)
James E. Blair972e3c72013-08-29 12:04:55 -0700873 self.assertEqual(len(self.history), 6)
James E. Blair6736beb2013-07-11 15:18:15 -0700874
James E. Blairdaabed22012-08-15 15:38:57 -0700875 def test_post(self):
876 "Test that post jobs run"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700877
Zhongyue Luo5d556072012-09-21 02:00:47 +0900878 e = {
879 "type": "ref-updated",
880 "submitter": {
881 "name": "User Name",
882 },
883 "refUpdate": {
884 "oldRev": "90f173846e3af9154517b88543ffbd1691f31366",
885 "newRev": "d479a0bfcb34da57a31adb2a595c0cf687812543",
886 "refName": "master",
887 "project": "org/project",
888 }
889 }
James E. Blairdaabed22012-08-15 15:38:57 -0700890 self.fake_gerrit.addEvent(e)
891 self.waitUntilSettled()
892
Monty Taylor6bef8ef2013-06-02 08:17:12 -0400893 job_names = [x.name for x in self.history]
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400894 self.assertEqual(len(self.history), 1)
895 self.assertIn('project-post', job_names)
James E. Blairc6294a52012-08-17 10:19:48 -0700896
897 def test_build_configuration_branch(self):
898 "Test that the right commits are on alternate branches"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700899
900 self.gearman_server.hold_jobs_in_queue = True
James E. Blairc6294a52012-08-17 10:19:48 -0700901 A = self.fake_gerrit.addFakeChange('org/project', 'mp', 'A')
902 B = self.fake_gerrit.addFakeChange('org/project', 'mp', 'B')
903 C = self.fake_gerrit.addFakeChange('org/project', 'mp', 'C')
904 A.addApproval('CRVW', 2)
905 B.addApproval('CRVW', 2)
906 C.addApproval('CRVW', 2)
907 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
908 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
909 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
910 self.waitUntilSettled()
911
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700912 self.gearman_server.release('.*-merge')
James E. Blairc6294a52012-08-17 10:19:48 -0700913 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700914 self.gearman_server.release('.*-merge')
James E. Blairc6294a52012-08-17 10:19:48 -0700915 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700916 self.gearman_server.release('.*-merge')
James E. Blairc6294a52012-08-17 10:19:48 -0700917 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -0700918 queue = self.gearman_server.getQueue()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700919 ref = self.getParameter(queue[-1], 'ZUUL_REF')
920 self.gearman_server.hold_jobs_in_queue = False
921 self.gearman_server.release()
James E. Blairc6294a52012-08-17 10:19:48 -0700922 self.waitUntilSettled()
923
Monty Taylorbc758832013-06-17 17:22:42 -0400924 path = os.path.join(self.git_root, "org/project")
James E. Blairc6294a52012-08-17 10:19:48 -0700925 repo = git.Repo(path)
926 repo_messages = [c.message.strip() for c in repo.iter_commits(ref)]
927 repo_messages.reverse()
James E. Blairc6294a52012-08-17 10:19:48 -0700928 correct_messages = ['initial commit', 'mp commit', 'A-1', 'B-1', 'C-1']
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400929 self.assertEqual(repo_messages, correct_messages)
James E. Blairc6294a52012-08-17 10:19:48 -0700930
931 def test_build_configuration_branch_interaction(self):
932 "Test that switching between branches works"
933 self.test_build_configuration()
934 self.test_build_configuration_branch()
935 # C has been merged, undo that
Monty Taylorbc758832013-06-17 17:22:42 -0400936 path = os.path.join(self.upstream_root, "org/project")
James E. Blairc6294a52012-08-17 10:19:48 -0700937 repo = git.Repo(path)
938 repo.heads.master.commit = repo.commit('init')
939 self.test_build_configuration()
940
941 def test_build_configuration_multi_branch(self):
942 "Test that dependent changes on multiple branches are merged"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700943
944 self.gearman_server.hold_jobs_in_queue = True
James E. Blairc6294a52012-08-17 10:19:48 -0700945 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
946 B = self.fake_gerrit.addFakeChange('org/project', 'mp', 'B')
947 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
948 A.addApproval('CRVW', 2)
949 B.addApproval('CRVW', 2)
950 C.addApproval('CRVW', 2)
951 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
952 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
953 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
954 self.waitUntilSettled()
James E. Blairbb1fe502014-03-04 10:15:06 -0800955 queue = self.gearman_server.getQueue()
956 job_A = None
957 for job in queue:
958 if 'project-merge' in job.name:
959 job_A = job
960 ref_A = self.getParameter(job_A, 'ZUUL_REF')
961 commit_A = self.getParameter(job_A, 'ZUUL_COMMIT')
962 self.log.debug("Got Zuul ref for change A: %s" % ref_A)
963 self.log.debug("Got Zuul commit for change A: %s" % commit_A)
James E. Blairc6294a52012-08-17 10:19:48 -0700964
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700965 self.gearman_server.release('.*-merge')
James E. Blairc6294a52012-08-17 10:19:48 -0700966 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -0700967 queue = self.gearman_server.getQueue()
James E. Blaird320d7e2013-07-30 16:36:20 -0700968 job_B = None
969 for job in queue:
970 if 'project-merge' in job.name:
971 job_B = job
972 ref_B = self.getParameter(job_B, 'ZUUL_REF')
James E. Blairbb1fe502014-03-04 10:15:06 -0800973 commit_B = self.getParameter(job_B, 'ZUUL_COMMIT')
James E. Blairf750aa02013-07-15 14:11:24 -0700974 self.log.debug("Got Zuul ref for change B: %s" % ref_B)
James E. Blairbb1fe502014-03-04 10:15:06 -0800975 self.log.debug("Got Zuul commit for change B: %s" % commit_B)
976
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700977 self.gearman_server.release('.*-merge')
James E. Blairc6294a52012-08-17 10:19:48 -0700978 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -0700979 queue = self.gearman_server.getQueue()
James E. Blaird320d7e2013-07-30 16:36:20 -0700980 for job in queue:
981 if 'project-merge' in job.name:
982 job_C = job
983 ref_C = self.getParameter(job_C, 'ZUUL_REF')
James E. Blairbb1fe502014-03-04 10:15:06 -0800984 commit_C = self.getParameter(job_C, 'ZUUL_COMMIT')
James E. Blairf750aa02013-07-15 14:11:24 -0700985 self.log.debug("Got Zuul ref for change C: %s" % ref_C)
James E. Blairbb1fe502014-03-04 10:15:06 -0800986 self.log.debug("Got Zuul commit for change C: %s" % commit_C)
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700987 self.gearman_server.hold_jobs_in_queue = False
988 self.gearman_server.release()
James E. Blairc6294a52012-08-17 10:19:48 -0700989 self.waitUntilSettled()
990
Monty Taylorbc758832013-06-17 17:22:42 -0400991 path = os.path.join(self.git_root, "org/project")
James E. Blairc6294a52012-08-17 10:19:48 -0700992 repo = git.Repo(path)
993
994 repo_messages = [c.message.strip()
James E. Blairf750aa02013-07-15 14:11:24 -0700995 for c in repo.iter_commits(ref_C)]
James E. Blairbb1fe502014-03-04 10:15:06 -0800996 repo_shas = [c.hexsha for c in repo.iter_commits(ref_C)]
James E. Blairc6294a52012-08-17 10:19:48 -0700997 repo_messages.reverse()
James E. Blairc6294a52012-08-17 10:19:48 -0700998 correct_messages = ['initial commit', 'A-1', 'C-1']
James E. Blairbb1fe502014-03-04 10:15:06 -0800999 # Ensure the right commits are in the history for this ref
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001000 self.assertEqual(repo_messages, correct_messages)
James E. Blairbb1fe502014-03-04 10:15:06 -08001001 # Ensure ZUUL_REF -> ZUUL_COMMIT
1002 self.assertEqual(repo_shas[0], commit_C)
James E. Blairc6294a52012-08-17 10:19:48 -07001003
1004 repo_messages = [c.message.strip()
James E. Blairf750aa02013-07-15 14:11:24 -07001005 for c in repo.iter_commits(ref_B)]
James E. Blairbb1fe502014-03-04 10:15:06 -08001006 repo_shas = [c.hexsha for c in repo.iter_commits(ref_B)]
James E. Blairc6294a52012-08-17 10:19:48 -07001007 repo_messages.reverse()
James E. Blairc6294a52012-08-17 10:19:48 -07001008 correct_messages = ['initial commit', 'mp commit', 'B-1']
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001009 self.assertEqual(repo_messages, correct_messages)
James E. Blairbb1fe502014-03-04 10:15:06 -08001010 self.assertEqual(repo_shas[0], commit_B)
1011
1012 repo_messages = [c.message.strip()
1013 for c in repo.iter_commits(ref_A)]
1014 repo_shas = [c.hexsha for c in repo.iter_commits(ref_A)]
1015 repo_messages.reverse()
1016 correct_messages = ['initial commit', 'A-1']
1017 self.assertEqual(repo_messages, correct_messages)
1018 self.assertEqual(repo_shas[0], commit_A)
1019
1020 self.assertNotEqual(ref_A, ref_B, ref_C)
1021 self.assertNotEqual(commit_A, commit_B, commit_C)
James E. Blair7f71c802012-08-22 13:04:32 -07001022
1023 def test_one_job_project(self):
1024 "Test that queueing works with one job"
1025 A = self.fake_gerrit.addFakeChange('org/one-job-project',
1026 'master', 'A')
1027 B = self.fake_gerrit.addFakeChange('org/one-job-project',
1028 'master', 'B')
1029 A.addApproval('CRVW', 2)
1030 B.addApproval('CRVW', 2)
1031 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1032 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1033 self.waitUntilSettled()
1034
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001035 self.assertEqual(A.data['status'], 'MERGED')
1036 self.assertEqual(A.reported, 2)
1037 self.assertEqual(B.data['status'], 'MERGED')
1038 self.assertEqual(B.reported, 2)
James E. Blaircaec0c52012-08-22 14:52:22 -07001039
Antoine Musso80edd5a2013-02-13 15:37:53 +01001040 def test_job_from_templates_launched(self):
1041 "Test whether a job generated via a template can be launched"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001042
Antoine Musso80edd5a2013-02-13 15:37:53 +01001043 A = self.fake_gerrit.addFakeChange(
1044 'org/templated-project', 'master', 'A')
1045 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1046 self.waitUntilSettled()
Antoine Musso80edd5a2013-02-13 15:37:53 +01001047
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001048 self.assertEqual(self.getJobFromHistory('project-test1').result,
1049 'SUCCESS')
1050 self.assertEqual(self.getJobFromHistory('project-test2').result,
1051 'SUCCESS')
Antoine Musso80edd5a2013-02-13 15:37:53 +01001052
James E. Blair3e98c022013-12-16 15:25:38 -08001053 def test_layered_templates(self):
1054 "Test whether a job generated via a template can be launched"
1055
1056 A = self.fake_gerrit.addFakeChange(
1057 'org/layered-project', 'master', 'A')
1058 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1059 self.waitUntilSettled()
1060
1061 self.assertEqual(self.getJobFromHistory('project-test1').result,
1062 'SUCCESS')
1063 self.assertEqual(self.getJobFromHistory('project-test2').result,
1064 'SUCCESS')
James E. Blairaea6cf62013-12-16 15:38:12 -08001065 self.assertEqual(self.getJobFromHistory('layered-project-test3'
1066 ).result, 'SUCCESS')
1067 self.assertEqual(self.getJobFromHistory('layered-project-test4'
1068 ).result, 'SUCCESS')
James E. Blair12a92b12014-03-26 11:54:53 -07001069 self.assertEqual(self.getJobFromHistory('layered-project-foo-test5'
1070 ).result, 'SUCCESS')
James E. Blair3e98c022013-12-16 15:25:38 -08001071 self.assertEqual(self.getJobFromHistory('project-test6').result,
1072 'SUCCESS')
1073
James E. Blaircaec0c52012-08-22 14:52:22 -07001074 def test_dependent_changes_dequeue(self):
1075 "Test that dependent patches are not needlessly tested"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001076
James E. Blaircaec0c52012-08-22 14:52:22 -07001077 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1078 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1079 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1080 A.addApproval('CRVW', 2)
1081 B.addApproval('CRVW', 2)
1082 C.addApproval('CRVW', 2)
1083
1084 M1 = self.fake_gerrit.addFakeChange('org/project', 'master', 'M1')
1085 M1.setMerged()
1086
1087 # C -> B -> A -> M1
1088
1089 C.setDependsOn(B, 1)
1090 B.setDependsOn(A, 1)
1091 A.setDependsOn(M1, 1)
1092
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001093 self.worker.addFailTest('project-merge', A)
James E. Blaircaec0c52012-08-22 14:52:22 -07001094
1095 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1096 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1097 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1098
1099 self.waitUntilSettled()
1100
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001101 self.assertEqual(A.data['status'], 'NEW')
1102 self.assertEqual(A.reported, 2)
1103 self.assertEqual(B.data['status'], 'NEW')
1104 self.assertEqual(B.reported, 2)
1105 self.assertEqual(C.data['status'], 'NEW')
1106 self.assertEqual(C.reported, 2)
1107 self.assertEqual(len(self.history), 1)
James E. Blairec590122012-08-22 15:19:31 -07001108
James E. Blair972e3c72013-08-29 12:04:55 -07001109 def test_failing_dependent_changes(self):
1110 "Test that failing dependent patches are taken out of stream"
1111 self.worker.hold_jobs_in_build = True
1112 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1113 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1114 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1115 D = self.fake_gerrit.addFakeChange('org/project', 'master', 'D')
1116 E = self.fake_gerrit.addFakeChange('org/project', 'master', 'E')
1117 A.addApproval('CRVW', 2)
1118 B.addApproval('CRVW', 2)
1119 C.addApproval('CRVW', 2)
1120 D.addApproval('CRVW', 2)
1121 E.addApproval('CRVW', 2)
1122
1123 # E, D -> C -> B, A
1124
1125 D.setDependsOn(C, 1)
1126 C.setDependsOn(B, 1)
1127
1128 self.worker.addFailTest('project-test1', B)
1129
1130 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1131 self.fake_gerrit.addEvent(D.addApproval('APRV', 1))
1132 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1133 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1134 self.fake_gerrit.addEvent(E.addApproval('APRV', 1))
1135
1136 self.waitUntilSettled()
1137 self.worker.release('.*-merge')
1138 self.waitUntilSettled()
1139 self.worker.release('.*-merge')
1140 self.waitUntilSettled()
1141 self.worker.release('.*-merge')
1142 self.waitUntilSettled()
1143 self.worker.release('.*-merge')
1144 self.waitUntilSettled()
1145 self.worker.release('.*-merge')
1146 self.waitUntilSettled()
1147
1148 self.worker.hold_jobs_in_build = False
1149 for build in self.builds:
1150 if build.parameters['ZUUL_CHANGE'] != '1':
1151 build.release()
1152 self.waitUntilSettled()
1153
1154 self.worker.release()
1155 self.waitUntilSettled()
1156
1157 self.assertEqual(A.data['status'], 'MERGED')
1158 self.assertEqual(A.reported, 2)
Jeremy Stanley10837132014-08-02 16:10:56 +00001159 self.assertIn('Build succeeded', A.messages[1])
James E. Blair972e3c72013-08-29 12:04:55 -07001160 self.assertEqual(B.data['status'], 'NEW')
1161 self.assertEqual(B.reported, 2)
Jeremy Stanley10837132014-08-02 16:10:56 +00001162 self.assertIn('Build failed', B.messages[1])
James E. Blair972e3c72013-08-29 12:04:55 -07001163 self.assertEqual(C.data['status'], 'NEW')
1164 self.assertEqual(C.reported, 2)
Jeremy Stanley10837132014-08-02 16:10:56 +00001165 self.assertIn('depends on a change', C.messages[1])
James E. Blair972e3c72013-08-29 12:04:55 -07001166 self.assertEqual(D.data['status'], 'NEW')
1167 self.assertEqual(D.reported, 2)
Jeremy Stanley10837132014-08-02 16:10:56 +00001168 self.assertIn('depends on a change', D.messages[1])
James E. Blair972e3c72013-08-29 12:04:55 -07001169 self.assertEqual(E.data['status'], 'MERGED')
1170 self.assertEqual(E.reported, 2)
Jeremy Stanley10837132014-08-02 16:10:56 +00001171 self.assertIn('Build succeeded', E.messages[1])
James E. Blair972e3c72013-08-29 12:04:55 -07001172 self.assertEqual(len(self.history), 18)
1173
James E. Blairec590122012-08-22 15:19:31 -07001174 def test_head_is_dequeued_once(self):
James E. Blair2fa50962013-01-30 21:50:41 -08001175 "Test that if a change at the head fails it is dequeued only once"
James E. Blairec590122012-08-22 15:19:31 -07001176 # If it's dequeued more than once, we should see extra
1177 # aborted jobs.
James E. Blairec590122012-08-22 15:19:31 -07001178
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001179 self.worker.hold_jobs_in_build = True
James E. Blairec590122012-08-22 15:19:31 -07001180 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
1181 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
1182 C = self.fake_gerrit.addFakeChange('org/project1', 'master', 'C')
1183 A.addApproval('CRVW', 2)
1184 B.addApproval('CRVW', 2)
1185 C.addApproval('CRVW', 2)
1186
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001187 self.worker.addFailTest('project1-test1', A)
1188 self.worker.addFailTest('project1-test2', A)
1189 self.worker.addFailTest('project1-project2-integration', A)
James E. Blairec590122012-08-22 15:19:31 -07001190
1191 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1192 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1193 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1194
1195 self.waitUntilSettled()
James E. Blairec590122012-08-22 15:19:31 -07001196
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001197 self.assertEqual(len(self.builds), 1)
1198 self.assertEqual(self.builds[0].name, 'project1-merge')
1199 self.assertTrue(self.job_has_changes(self.builds[0], A))
James E. Blairec590122012-08-22 15:19:31 -07001200
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001201 self.worker.release('.*-merge')
James E. Blairec590122012-08-22 15:19:31 -07001202 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001203 self.worker.release('.*-merge')
James E. Blairec590122012-08-22 15:19:31 -07001204 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001205 self.worker.release('.*-merge')
James E. Blairec590122012-08-22 15:19:31 -07001206 self.waitUntilSettled()
1207
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001208 self.assertEqual(len(self.builds), 9)
1209 self.assertEqual(self.builds[0].name, 'project1-test1')
1210 self.assertEqual(self.builds[1].name, 'project1-test2')
1211 self.assertEqual(self.builds[2].name, 'project1-project2-integration')
1212 self.assertEqual(self.builds[3].name, 'project1-test1')
1213 self.assertEqual(self.builds[4].name, 'project1-test2')
1214 self.assertEqual(self.builds[5].name, 'project1-project2-integration')
1215 self.assertEqual(self.builds[6].name, 'project1-test1')
1216 self.assertEqual(self.builds[7].name, 'project1-test2')
1217 self.assertEqual(self.builds[8].name, 'project1-project2-integration')
James E. Blairec590122012-08-22 15:19:31 -07001218
Monty Taylor6bef8ef2013-06-02 08:17:12 -04001219 self.release(self.builds[0])
James E. Blairec590122012-08-22 15:19:31 -07001220 self.waitUntilSettled()
1221
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001222 self.assertEqual(len(self.builds), 3) # test2,integration, merge for B
1223 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 6)
James E. Blairec590122012-08-22 15:19:31 -07001224
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001225 self.worker.hold_jobs_in_build = False
1226 self.worker.release()
James E. Blairec590122012-08-22 15:19:31 -07001227 self.waitUntilSettled()
1228
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001229 self.assertEqual(len(self.builds), 0)
1230 self.assertEqual(len(self.history), 20)
James E. Blaircaec0c52012-08-22 14:52:22 -07001231
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001232 self.assertEqual(A.data['status'], 'NEW')
1233 self.assertEqual(B.data['status'], 'MERGED')
1234 self.assertEqual(C.data['status'], 'MERGED')
1235 self.assertEqual(A.reported, 2)
1236 self.assertEqual(B.reported, 2)
1237 self.assertEqual(C.reported, 2)
James E. Blair4ec821f2012-08-23 15:28:28 -07001238
1239 def test_nonvoting_job(self):
1240 "Test that non-voting jobs don't vote."
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001241
James E. Blair4ec821f2012-08-23 15:28:28 -07001242 A = self.fake_gerrit.addFakeChange('org/nonvoting-project',
1243 'master', 'A')
1244 A.addApproval('CRVW', 2)
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001245 self.worker.addFailTest('nonvoting-project-test2', A)
James E. Blair4ec821f2012-08-23 15:28:28 -07001246 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1247
1248 self.waitUntilSettled()
James E. Blair4ec821f2012-08-23 15:28:28 -07001249
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001250 self.assertEqual(A.data['status'], 'MERGED')
1251 self.assertEqual(A.reported, 2)
1252 self.assertEqual(
1253 self.getJobFromHistory('nonvoting-project-merge').result,
1254 'SUCCESS')
1255 self.assertEqual(
1256 self.getJobFromHistory('nonvoting-project-test1').result,
1257 'SUCCESS')
1258 self.assertEqual(
1259 self.getJobFromHistory('nonvoting-project-test2').result,
1260 'FAILURE')
James E. Blaire0487072012-08-29 17:38:31 -07001261
James E. Blair5821bd92015-09-16 08:48:15 -07001262 for build in self.builds:
1263 self.assertEqual(build.parameters['ZUUL_VOTING'], '0')
1264
James E. Blaire0487072012-08-29 17:38:31 -07001265 def test_check_queue_success(self):
1266 "Test successful check queue jobs."
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001267
James E. Blaire0487072012-08-29 17:38:31 -07001268 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1269 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1270
1271 self.waitUntilSettled()
James E. Blaire0487072012-08-29 17:38:31 -07001272
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001273 self.assertEqual(A.data['status'], 'NEW')
1274 self.assertEqual(A.reported, 1)
1275 self.assertEqual(self.getJobFromHistory('project-merge').result,
1276 'SUCCESS')
1277 self.assertEqual(self.getJobFromHistory('project-test1').result,
1278 'SUCCESS')
1279 self.assertEqual(self.getJobFromHistory('project-test2').result,
1280 'SUCCESS')
James E. Blaire0487072012-08-29 17:38:31 -07001281
1282 def test_check_queue_failure(self):
1283 "Test failed check queue jobs."
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001284
James E. Blaire0487072012-08-29 17:38:31 -07001285 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001286 self.worker.addFailTest('project-test2', A)
James E. Blaire0487072012-08-29 17:38:31 -07001287 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1288
1289 self.waitUntilSettled()
James E. Blaire0487072012-08-29 17:38:31 -07001290
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001291 self.assertEqual(A.data['status'], 'NEW')
1292 self.assertEqual(A.reported, 1)
1293 self.assertEqual(self.getJobFromHistory('project-merge').result,
James E. Blair78e31b32013-07-09 09:11:34 -07001294 'SUCCESS')
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001295 self.assertEqual(self.getJobFromHistory('project-test1').result,
1296 'SUCCESS')
1297 self.assertEqual(self.getJobFromHistory('project-test2').result,
1298 'FAILURE')
James E. Blair127bc182012-08-28 15:55:15 -07001299
1300 def test_dependent_behind_dequeue(self):
1301 "test that dependent changes behind dequeued changes work"
1302 # This complicated test is a reproduction of a real life bug
1303 self.sched.reconfigure(self.config)
James E. Blair127bc182012-08-28 15:55:15 -07001304
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001305 self.worker.hold_jobs_in_build = True
James E. Blair127bc182012-08-28 15:55:15 -07001306 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
1307 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
1308 C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
1309 D = self.fake_gerrit.addFakeChange('org/project2', 'master', 'D')
1310 E = self.fake_gerrit.addFakeChange('org/project2', 'master', 'E')
1311 F = self.fake_gerrit.addFakeChange('org/project3', 'master', 'F')
1312 D.setDependsOn(C, 1)
1313 E.setDependsOn(D, 1)
1314 A.addApproval('CRVW', 2)
1315 B.addApproval('CRVW', 2)
1316 C.addApproval('CRVW', 2)
1317 D.addApproval('CRVW', 2)
1318 E.addApproval('CRVW', 2)
1319 F.addApproval('CRVW', 2)
1320
1321 A.fail_merge = True
James E. Blair127bc182012-08-28 15:55:15 -07001322
1323 # Change object re-use in the gerrit trigger is hidden if
1324 # changes are added in quick succession; waiting makes it more
1325 # like real life.
1326 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1327 self.waitUntilSettled()
1328 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1329 self.waitUntilSettled()
1330
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001331 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001332 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001333 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001334 self.waitUntilSettled()
1335
1336 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1337 self.waitUntilSettled()
1338 self.fake_gerrit.addEvent(D.addApproval('APRV', 1))
1339 self.waitUntilSettled()
1340 self.fake_gerrit.addEvent(E.addApproval('APRV', 1))
1341 self.waitUntilSettled()
1342 self.fake_gerrit.addEvent(F.addApproval('APRV', 1))
1343 self.waitUntilSettled()
1344
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001345 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001346 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001347 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001348 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001349 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001350 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001351 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001352 self.waitUntilSettled()
1353
1354 # all jobs running
James E. Blaire955e062012-10-08 09:49:03 -07001355
1356 # Grab pointers to the jobs we want to release before
1357 # releasing any, because list indexes may change as
1358 # the jobs complete.
Monty Taylor6bef8ef2013-06-02 08:17:12 -04001359 a, b, c = self.builds[:3]
James E. Blaire955e062012-10-08 09:49:03 -07001360 a.release()
1361 b.release()
1362 c.release()
James E. Blair127bc182012-08-28 15:55:15 -07001363 self.waitUntilSettled()
1364
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001365 self.worker.hold_jobs_in_build = False
1366 self.worker.release()
James E. Blair127bc182012-08-28 15:55:15 -07001367 self.waitUntilSettled()
1368
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001369 self.assertEqual(A.data['status'], 'NEW')
1370 self.assertEqual(B.data['status'], 'MERGED')
1371 self.assertEqual(C.data['status'], 'MERGED')
1372 self.assertEqual(D.data['status'], 'MERGED')
1373 self.assertEqual(E.data['status'], 'MERGED')
1374 self.assertEqual(F.data['status'], 'MERGED')
James E. Blair127bc182012-08-28 15:55:15 -07001375
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001376 self.assertEqual(A.reported, 2)
1377 self.assertEqual(B.reported, 2)
1378 self.assertEqual(C.reported, 2)
1379 self.assertEqual(D.reported, 2)
1380 self.assertEqual(E.reported, 2)
1381 self.assertEqual(F.reported, 2)
James E. Blair127bc182012-08-28 15:55:15 -07001382
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001383 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 15)
1384 self.assertEqual(len(self.history), 44)
James E. Blair05fed602012-09-07 12:45:24 -07001385
1386 def test_merger_repack(self):
1387 "Test that the merger works after a repack"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001388
James E. Blair05fed602012-09-07 12:45:24 -07001389 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1390 A.addApproval('CRVW', 2)
1391 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1392 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001393 self.assertEqual(self.getJobFromHistory('project-merge').result,
1394 'SUCCESS')
1395 self.assertEqual(self.getJobFromHistory('project-test1').result,
1396 'SUCCESS')
1397 self.assertEqual(self.getJobFromHistory('project-test2').result,
1398 'SUCCESS')
1399 self.assertEqual(A.data['status'], 'MERGED')
1400 self.assertEqual(A.reported, 2)
James E. Blair05fed602012-09-07 12:45:24 -07001401 self.assertEmptyQueues()
James E. Blair4ca985f2013-05-30 12:27:43 -07001402 self.worker.build_history = []
James E. Blair05fed602012-09-07 12:45:24 -07001403
Monty Taylorbc758832013-06-17 17:22:42 -04001404 path = os.path.join(self.git_root, "org/project")
1405 print repack_repo(path)
James E. Blair05fed602012-09-07 12:45:24 -07001406
1407 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1408 A.addApproval('CRVW', 2)
1409 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1410 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001411 self.assertEqual(self.getJobFromHistory('project-merge').result,
1412 'SUCCESS')
1413 self.assertEqual(self.getJobFromHistory('project-test1').result,
1414 'SUCCESS')
1415 self.assertEqual(self.getJobFromHistory('project-test2').result,
1416 'SUCCESS')
1417 self.assertEqual(A.data['status'], 'MERGED')
1418 self.assertEqual(A.reported, 2)
James E. Blair7ee88a22012-09-12 18:59:31 +02001419
James E. Blair4886f282012-11-15 09:27:33 -08001420 def test_merger_repack_large_change(self):
1421 "Test that the merger works with large changes after a repack"
1422 # https://bugs.launchpad.net/zuul/+bug/1078946
James E. Blairac2c3242014-01-24 13:38:51 -08001423 # This test assumes the repo is already cloned; make sure it is
1424 url = self.sched.triggers['gerrit'].getGitUrl(
1425 self.sched.layout.projects['org/project1'])
James E. Blair4076e2b2014-01-28 12:42:20 -08001426 self.merge_server.merger.addProject('org/project1', url)
James E. Blair4886f282012-11-15 09:27:33 -08001427 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
1428 A.addPatchset(large=True)
Monty Taylorbc758832013-06-17 17:22:42 -04001429 path = os.path.join(self.upstream_root, "org/project1")
1430 print repack_repo(path)
1431 path = os.path.join(self.git_root, "org/project1")
1432 print repack_repo(path)
James E. Blair4886f282012-11-15 09:27:33 -08001433
1434 A.addApproval('CRVW', 2)
1435 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1436 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001437 self.assertEqual(self.getJobFromHistory('project1-merge').result,
1438 'SUCCESS')
1439 self.assertEqual(self.getJobFromHistory('project1-test1').result,
1440 'SUCCESS')
1441 self.assertEqual(self.getJobFromHistory('project1-test2').result,
1442 'SUCCESS')
1443 self.assertEqual(A.data['status'], 'MERGED')
1444 self.assertEqual(A.reported, 2)
James E. Blair4886f282012-11-15 09:27:33 -08001445
James E. Blair7ee88a22012-09-12 18:59:31 +02001446 def test_nonexistent_job(self):
1447 "Test launching a job that doesn't exist"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001448 # Set to the state immediately after a restart
1449 self.resetGearmanServer()
1450 self.launcher.negative_function_cache_ttl = 0
James E. Blair7ee88a22012-09-12 18:59:31 +02001451
1452 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1453 A.addApproval('CRVW', 2)
1454 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1455 # There may be a thread about to report a lost change
1456 while A.reported < 2:
1457 self.waitUntilSettled()
Monty Taylor6bef8ef2013-06-02 08:17:12 -04001458 job_names = [x.name for x in self.history]
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001459 self.assertFalse(job_names)
1460 self.assertEqual(A.data['status'], 'NEW')
1461 self.assertEqual(A.reported, 2)
James E. Blair7ee88a22012-09-12 18:59:31 +02001462 self.assertEmptyQueues()
1463
1464 # Make sure things still work:
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001465 self.registerJobs()
James E. Blair7ee88a22012-09-12 18:59:31 +02001466 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1467 A.addApproval('CRVW', 2)
1468 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1469 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001470 self.assertEqual(self.getJobFromHistory('project-merge').result,
1471 'SUCCESS')
1472 self.assertEqual(self.getJobFromHistory('project-test1').result,
1473 'SUCCESS')
1474 self.assertEqual(self.getJobFromHistory('project-test2').result,
1475 'SUCCESS')
1476 self.assertEqual(A.data['status'], 'MERGED')
1477 self.assertEqual(A.reported, 2)
James E. Blairf62d4282012-12-31 17:01:50 -08001478
1479 def test_single_nonexistent_post_job(self):
1480 "Test launching a single post job that doesn't exist"
James E. Blairf62d4282012-12-31 17:01:50 -08001481 e = {
1482 "type": "ref-updated",
1483 "submitter": {
1484 "name": "User Name",
1485 },
1486 "refUpdate": {
1487 "oldRev": "90f173846e3af9154517b88543ffbd1691f31366",
1488 "newRev": "d479a0bfcb34da57a31adb2a595c0cf687812543",
1489 "refName": "master",
1490 "project": "org/project",
1491 }
1492 }
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001493 # Set to the state immediately after a restart
1494 self.resetGearmanServer()
1495 self.launcher.negative_function_cache_ttl = 0
1496
James E. Blairf62d4282012-12-31 17:01:50 -08001497 self.fake_gerrit.addEvent(e)
1498 self.waitUntilSettled()
1499
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001500 self.assertEqual(len(self.history), 0)
James E. Blair2fa50962013-01-30 21:50:41 -08001501
1502 def test_new_patchset_dequeues_old(self):
1503 "Test that a new patchset causes the old to be dequeued"
1504 # D -> C (depends on B) -> B (depends on A) -> A -> M
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001505 self.worker.hold_jobs_in_build = True
James E. Blair2fa50962013-01-30 21:50:41 -08001506 M = self.fake_gerrit.addFakeChange('org/project', 'master', 'M')
1507 M.setMerged()
1508
1509 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1510 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1511 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1512 D = self.fake_gerrit.addFakeChange('org/project', 'master', 'D')
1513 A.addApproval('CRVW', 2)
1514 B.addApproval('CRVW', 2)
1515 C.addApproval('CRVW', 2)
1516 D.addApproval('CRVW', 2)
1517
1518 C.setDependsOn(B, 1)
1519 B.setDependsOn(A, 1)
1520 A.setDependsOn(M, 1)
1521
1522 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1523 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1524 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1525 self.fake_gerrit.addEvent(D.addApproval('APRV', 1))
1526 self.waitUntilSettled()
1527
1528 B.addPatchset()
1529 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(2))
1530 self.waitUntilSettled()
1531
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001532 self.worker.hold_jobs_in_build = False
1533 self.worker.release()
James E. Blair2fa50962013-01-30 21:50:41 -08001534 self.waitUntilSettled()
1535
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001536 self.assertEqual(A.data['status'], 'MERGED')
1537 self.assertEqual(A.reported, 2)
1538 self.assertEqual(B.data['status'], 'NEW')
1539 self.assertEqual(B.reported, 2)
1540 self.assertEqual(C.data['status'], 'NEW')
1541 self.assertEqual(C.reported, 2)
1542 self.assertEqual(D.data['status'], 'MERGED')
1543 self.assertEqual(D.reported, 2)
1544 self.assertEqual(len(self.history), 9) # 3 each for A, B, D.
James E. Blair2fa50962013-01-30 21:50:41 -08001545
James E. Blairba437362015-02-07 11:41:52 -08001546 def test_new_patchset_check(self):
1547 "Test a new patchset in check"
Antoine Mussobd86a312014-01-08 14:51:33 +01001548
1549 self.worker.hold_jobs_in_build = True
1550
1551 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
James E. Blairba437362015-02-07 11:41:52 -08001552 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1553 check_pipeline = self.sched.layout.pipelines['check']
1554
1555 # Add two git-dependent changes
1556 B.setDependsOn(A, 1)
1557 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1558 self.waitUntilSettled()
Antoine Mussobd86a312014-01-08 14:51:33 +01001559 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1560 self.waitUntilSettled()
James E. Blairba437362015-02-07 11:41:52 -08001561
1562 # A live item, and a non-live/live pair
1563 items = check_pipeline.getAllItems()
1564 self.assertEqual(len(items), 3)
1565
1566 self.assertEqual(items[0].change.number, '1')
1567 self.assertEqual(items[0].change.patchset, '1')
1568 self.assertFalse(items[0].live)
1569
1570 self.assertEqual(items[1].change.number, '2')
1571 self.assertEqual(items[1].change.patchset, '1')
1572 self.assertTrue(items[1].live)
1573
1574 self.assertEqual(items[2].change.number, '1')
1575 self.assertEqual(items[2].change.patchset, '1')
1576 self.assertTrue(items[2].live)
1577
1578 # Add a new patchset to A
1579 A.addPatchset()
1580 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
1581 self.waitUntilSettled()
1582
1583 # The live copy of A,1 should be gone, but the non-live and B
1584 # should continue, and we should have a new A,2
1585 items = check_pipeline.getAllItems()
1586 self.assertEqual(len(items), 3)
1587
1588 self.assertEqual(items[0].change.number, '1')
1589 self.assertEqual(items[0].change.patchset, '1')
1590 self.assertFalse(items[0].live)
1591
1592 self.assertEqual(items[1].change.number, '2')
1593 self.assertEqual(items[1].change.patchset, '1')
1594 self.assertTrue(items[1].live)
1595
1596 self.assertEqual(items[2].change.number, '1')
1597 self.assertEqual(items[2].change.patchset, '2')
1598 self.assertTrue(items[2].live)
1599
1600 # Add a new patchset to B
1601 B.addPatchset()
1602 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(2))
1603 self.waitUntilSettled()
1604
1605 # The live copy of B,1 should be gone, and it's non-live copy of A,1
1606 # but we should have a new B,2 (still based on A,1)
1607 items = check_pipeline.getAllItems()
1608 self.assertEqual(len(items), 3)
1609
1610 self.assertEqual(items[0].change.number, '1')
1611 self.assertEqual(items[0].change.patchset, '2')
1612 self.assertTrue(items[0].live)
1613
1614 self.assertEqual(items[1].change.number, '1')
1615 self.assertEqual(items[1].change.patchset, '1')
1616 self.assertFalse(items[1].live)
1617
1618 self.assertEqual(items[2].change.number, '2')
1619 self.assertEqual(items[2].change.patchset, '2')
1620 self.assertTrue(items[2].live)
1621
1622 self.builds[0].release()
1623 self.waitUntilSettled()
1624 self.builds[0].release()
1625 self.waitUntilSettled()
1626 self.worker.hold_jobs_in_build = False
1627 self.worker.release()
1628 self.waitUntilSettled()
1629
1630 self.assertEqual(A.reported, 1)
1631 self.assertEqual(B.reported, 1)
1632 self.assertEqual(self.history[0].result, 'ABORTED')
1633 self.assertEqual(self.history[0].changes, '1,1')
1634 self.assertEqual(self.history[1].result, 'ABORTED')
1635 self.assertEqual(self.history[1].changes, '1,1 2,1')
1636 self.assertEqual(self.history[2].result, 'SUCCESS')
1637 self.assertEqual(self.history[2].changes, '1,2')
1638 self.assertEqual(self.history[3].result, 'SUCCESS')
1639 self.assertEqual(self.history[3].changes, '1,1 2,2')
1640
1641 def test_abandoned_gate(self):
1642 "Test that an abandoned change is dequeued from gate"
1643
1644 self.worker.hold_jobs_in_build = True
1645
1646 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1647 A.addApproval('CRVW', 2)
1648 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1649 self.waitUntilSettled()
Antoine Mussobd86a312014-01-08 14:51:33 +01001650 self.assertEqual(len(self.builds), 1, "One job being built (on hold)")
1651 self.assertEqual(self.builds[0].name, 'project-merge')
1652
1653 self.fake_gerrit.addEvent(A.getChangeAbandonedEvent())
1654 self.waitUntilSettled()
1655
Antoine Mussobd86a312014-01-08 14:51:33 +01001656 self.worker.release('.*-merge')
1657 self.waitUntilSettled()
1658
1659 self.assertEqual(len(self.builds), 0, "No job running")
Antoine Mussobd86a312014-01-08 14:51:33 +01001660 self.assertEqual(len(self.history), 1, "Only one build in history")
1661 self.assertEqual(self.history[0].result, 'ABORTED',
James E. Blairba437362015-02-07 11:41:52 -08001662 "Build should have been aborted")
1663 self.assertEqual(A.reported, 1,
1664 "Abandoned gate change should report only start")
1665
1666 def test_abandoned_check(self):
1667 "Test that an abandoned change is dequeued from check"
1668
1669 self.worker.hold_jobs_in_build = True
1670
1671 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1672 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1673 check_pipeline = self.sched.layout.pipelines['check']
1674
1675 # Add two git-dependent changes
1676 B.setDependsOn(A, 1)
1677 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1678 self.waitUntilSettled()
1679 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1680 self.waitUntilSettled()
1681 # A live item, and a non-live/live pair
1682 items = check_pipeline.getAllItems()
1683 self.assertEqual(len(items), 3)
1684
1685 self.assertEqual(items[0].change.number, '1')
1686 self.assertFalse(items[0].live)
1687
1688 self.assertEqual(items[1].change.number, '2')
1689 self.assertTrue(items[1].live)
1690
1691 self.assertEqual(items[2].change.number, '1')
1692 self.assertTrue(items[2].live)
1693
1694 # Abandon A
1695 self.fake_gerrit.addEvent(A.getChangeAbandonedEvent())
1696 self.waitUntilSettled()
1697
1698 # The live copy of A should be gone, but the non-live and B
1699 # should continue
1700 items = check_pipeline.getAllItems()
1701 self.assertEqual(len(items), 2)
1702
1703 self.assertEqual(items[0].change.number, '1')
1704 self.assertFalse(items[0].live)
1705
1706 self.assertEqual(items[1].change.number, '2')
1707 self.assertTrue(items[1].live)
1708
1709 self.worker.hold_jobs_in_build = False
1710 self.worker.release()
1711 self.waitUntilSettled()
1712
1713 self.assertEqual(len(self.history), 4)
1714 self.assertEqual(self.history[0].result, 'ABORTED',
Antoine Mussobd86a312014-01-08 14:51:33 +01001715 'Build should have been aborted')
1716 self.assertEqual(A.reported, 0, "Abandoned change should not report")
James E. Blairba437362015-02-07 11:41:52 -08001717 self.assertEqual(B.reported, 1, "Change should report")
Antoine Mussobd86a312014-01-08 14:51:33 +01001718
Steve Varnau7b78b312015-04-03 14:49:46 -07001719 def test_abandoned_not_timer(self):
1720 "Test that an abandoned change does not cancel timer jobs"
1721
1722 self.worker.hold_jobs_in_build = True
1723
1724 # Start timer trigger - also org/project
1725 self.config.set('zuul', 'layout_config',
1726 'tests/fixtures/layout-idle.yaml')
1727 self.sched.reconfigure(self.config)
1728 self.registerJobs()
1729 # The pipeline triggers every second, so we should have seen
1730 # several by now.
1731 time.sleep(5)
1732 self.waitUntilSettled()
1733 # Stop queuing timer triggered jobs so that the assertions
1734 # below don't race against more jobs being queued.
1735 self.config.set('zuul', 'layout_config',
1736 'tests/fixtures/layout-no-timer.yaml')
1737 self.sched.reconfigure(self.config)
1738 self.registerJobs()
1739 self.assertEqual(len(self.builds), 2, "Two timer jobs")
1740
1741 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1742 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1743 self.waitUntilSettled()
1744 self.assertEqual(len(self.builds), 3, "One change plus two timer jobs")
1745
1746 self.fake_gerrit.addEvent(A.getChangeAbandonedEvent())
1747 self.waitUntilSettled()
1748
1749 self.assertEqual(len(self.builds), 2, "Two timer jobs remain")
1750
1751 self.worker.release()
1752 self.waitUntilSettled()
1753
Arx Cruzb1b010d2013-10-28 19:49:59 -02001754 def test_zuul_url_return(self):
1755 "Test if ZUUL_URL is returning when zuul_url is set in zuul.conf"
James E. Blair4076e2b2014-01-28 12:42:20 -08001756 self.assertTrue(self.sched.config.has_option('merger', 'zuul_url'))
Arx Cruzb1b010d2013-10-28 19:49:59 -02001757 self.worker.hold_jobs_in_build = True
1758
1759 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1760 A.addApproval('CRVW', 2)
1761 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1762 self.waitUntilSettled()
1763
1764 self.assertEqual(len(self.builds), 1)
1765 for build in self.builds:
1766 self.assertTrue('ZUUL_URL' in build.parameters)
1767
1768 self.worker.hold_jobs_in_build = False
1769 self.worker.release()
1770 self.waitUntilSettled()
1771
James E. Blair2fa50962013-01-30 21:50:41 -08001772 def test_new_patchset_dequeues_old_on_head(self):
1773 "Test that a new patchset causes the old to be dequeued (at head)"
1774 # D -> C (depends on B) -> B (depends on A) -> A -> M
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001775 self.worker.hold_jobs_in_build = True
James E. Blair2fa50962013-01-30 21:50:41 -08001776 M = self.fake_gerrit.addFakeChange('org/project', 'master', 'M')
1777 M.setMerged()
1778 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1779 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1780 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1781 D = self.fake_gerrit.addFakeChange('org/project', 'master', 'D')
1782 A.addApproval('CRVW', 2)
1783 B.addApproval('CRVW', 2)
1784 C.addApproval('CRVW', 2)
1785 D.addApproval('CRVW', 2)
1786
1787 C.setDependsOn(B, 1)
1788 B.setDependsOn(A, 1)
1789 A.setDependsOn(M, 1)
1790
1791 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1792 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1793 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1794 self.fake_gerrit.addEvent(D.addApproval('APRV', 1))
1795 self.waitUntilSettled()
1796
1797 A.addPatchset()
1798 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
1799 self.waitUntilSettled()
1800
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001801 self.worker.hold_jobs_in_build = False
1802 self.worker.release()
James E. Blair2fa50962013-01-30 21:50:41 -08001803 self.waitUntilSettled()
1804
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001805 self.assertEqual(A.data['status'], 'NEW')
1806 self.assertEqual(A.reported, 2)
1807 self.assertEqual(B.data['status'], 'NEW')
1808 self.assertEqual(B.reported, 2)
1809 self.assertEqual(C.data['status'], 'NEW')
1810 self.assertEqual(C.reported, 2)
1811 self.assertEqual(D.data['status'], 'MERGED')
1812 self.assertEqual(D.reported, 2)
1813 self.assertEqual(len(self.history), 7)
James E. Blair2fa50962013-01-30 21:50:41 -08001814
1815 def test_new_patchset_dequeues_old_without_dependents(self):
1816 "Test that a new patchset causes only the old to be dequeued"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001817 self.worker.hold_jobs_in_build = True
James E. Blair2fa50962013-01-30 21:50:41 -08001818 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1819 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1820 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1821 A.addApproval('CRVW', 2)
1822 B.addApproval('CRVW', 2)
1823 C.addApproval('CRVW', 2)
1824
1825 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1826 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1827 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1828 self.waitUntilSettled()
1829
1830 B.addPatchset()
1831 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(2))
1832 self.waitUntilSettled()
1833
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001834 self.worker.hold_jobs_in_build = False
1835 self.worker.release()
James E. Blair2fa50962013-01-30 21:50:41 -08001836 self.waitUntilSettled()
1837
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001838 self.assertEqual(A.data['status'], 'MERGED')
1839 self.assertEqual(A.reported, 2)
1840 self.assertEqual(B.data['status'], 'NEW')
1841 self.assertEqual(B.reported, 2)
1842 self.assertEqual(C.data['status'], 'MERGED')
1843 self.assertEqual(C.reported, 2)
1844 self.assertEqual(len(self.history), 9)
James E. Blair2fa50962013-01-30 21:50:41 -08001845
1846 def test_new_patchset_dequeues_old_independent_queue(self):
1847 "Test that a new patchset causes the old to be dequeued (independent)"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001848 self.worker.hold_jobs_in_build = True
James E. Blair2fa50962013-01-30 21:50:41 -08001849 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1850 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1851 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1852 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1853 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1854 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
1855 self.waitUntilSettled()
1856
1857 B.addPatchset()
1858 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(2))
1859 self.waitUntilSettled()
1860
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001861 self.worker.hold_jobs_in_build = False
1862 self.worker.release()
James E. Blair2fa50962013-01-30 21:50:41 -08001863 self.waitUntilSettled()
1864
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001865 self.assertEqual(A.data['status'], 'NEW')
1866 self.assertEqual(A.reported, 1)
1867 self.assertEqual(B.data['status'], 'NEW')
1868 self.assertEqual(B.reported, 1)
1869 self.assertEqual(C.data['status'], 'NEW')
1870 self.assertEqual(C.reported, 1)
1871 self.assertEqual(len(self.history), 10)
1872 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 1)
James E. Blair7d0dedc2013-02-21 17:26:09 -08001873
James E. Blair18c64442014-03-18 10:14:45 -07001874 def test_noop_job(self):
1875 "Test that the internal noop job works"
1876 A = self.fake_gerrit.addFakeChange('org/noop-project', 'master', 'A')
1877 A.addApproval('CRVW', 2)
1878 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1879 self.waitUntilSettled()
1880
1881 self.assertEqual(len(self.gearman_server.getQueue()), 0)
1882 self.assertTrue(self.sched._areAllBuildsComplete())
1883 self.assertEqual(len(self.history), 0)
1884 self.assertEqual(A.data['status'], 'MERGED')
1885 self.assertEqual(A.reported, 2)
1886
Evgeny Antyshevd6e546c2015-06-11 15:13:57 +00001887 def test_no_job_project(self):
1888 "Test that reports with no jobs don't get sent"
1889 A = self.fake_gerrit.addFakeChange('org/no-jobs-project',
1890 'master', 'A')
1891 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1892 self.waitUntilSettled()
1893
1894 # Change wasn't reported to
1895 self.assertEqual(A.reported, False)
1896
1897 # Check queue is empty afterwards
1898 check_pipeline = self.sched.layout.pipelines['check']
1899 items = check_pipeline.getAllItems()
1900 self.assertEqual(len(items), 0)
1901
1902 self.assertEqual(len(self.history), 0)
1903
James E. Blair7d0dedc2013-02-21 17:26:09 -08001904 def test_zuul_refs(self):
1905 "Test that zuul refs exist and have the right changes"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001906 self.worker.hold_jobs_in_build = True
James E. Blair7d0dedc2013-02-21 17:26:09 -08001907 M1 = self.fake_gerrit.addFakeChange('org/project1', 'master', 'M1')
1908 M1.setMerged()
1909 M2 = self.fake_gerrit.addFakeChange('org/project2', 'master', 'M2')
1910 M2.setMerged()
1911
1912 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
1913 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
1914 C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
1915 D = self.fake_gerrit.addFakeChange('org/project2', 'master', 'D')
1916 A.addApproval('CRVW', 2)
1917 B.addApproval('CRVW', 2)
1918 C.addApproval('CRVW', 2)
1919 D.addApproval('CRVW', 2)
1920 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1921 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1922 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1923 self.fake_gerrit.addEvent(D.addApproval('APRV', 1))
1924
1925 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001926 self.worker.release('.*-merge')
James E. Blair7d0dedc2013-02-21 17:26:09 -08001927 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001928 self.worker.release('.*-merge')
James E. Blair7d0dedc2013-02-21 17:26:09 -08001929 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001930 self.worker.release('.*-merge')
James E. Blair7d0dedc2013-02-21 17:26:09 -08001931 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001932 self.worker.release('.*-merge')
James E. Blair7d0dedc2013-02-21 17:26:09 -08001933 self.waitUntilSettled()
1934
James E. Blair7d0dedc2013-02-21 17:26:09 -08001935 a_zref = b_zref = c_zref = d_zref = None
Monty Taylor6bef8ef2013-06-02 08:17:12 -04001936 for x in self.builds:
James E. Blair7d0dedc2013-02-21 17:26:09 -08001937 if x.parameters['ZUUL_CHANGE'] == '3':
1938 a_zref = x.parameters['ZUUL_REF']
1939 if x.parameters['ZUUL_CHANGE'] == '4':
1940 b_zref = x.parameters['ZUUL_REF']
1941 if x.parameters['ZUUL_CHANGE'] == '5':
1942 c_zref = x.parameters['ZUUL_REF']
1943 if x.parameters['ZUUL_CHANGE'] == '6':
1944 d_zref = x.parameters['ZUUL_REF']
1945
1946 # There are... four... refs.
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001947 self.assertIsNotNone(a_zref)
1948 self.assertIsNotNone(b_zref)
1949 self.assertIsNotNone(c_zref)
1950 self.assertIsNotNone(d_zref)
James E. Blair7d0dedc2013-02-21 17:26:09 -08001951
1952 # And they should all be different
1953 refs = set([a_zref, b_zref, c_zref, d_zref])
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001954 self.assertEqual(len(refs), 4)
James E. Blair7d0dedc2013-02-21 17:26:09 -08001955
1956 # a ref should have a, not b, and should not be in project2
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001957 self.assertTrue(self.ref_has_change(a_zref, A))
1958 self.assertFalse(self.ref_has_change(a_zref, B))
1959 self.assertFalse(self.ref_has_change(a_zref, M2))
James E. Blair7d0dedc2013-02-21 17:26:09 -08001960
1961 # b ref should have a and b, and should not be in project2
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001962 self.assertTrue(self.ref_has_change(b_zref, A))
1963 self.assertTrue(self.ref_has_change(b_zref, B))
1964 self.assertFalse(self.ref_has_change(b_zref, M2))
James E. Blair7d0dedc2013-02-21 17:26:09 -08001965
1966 # c ref should have a and b in 1, c in 2
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001967 self.assertTrue(self.ref_has_change(c_zref, A))
1968 self.assertTrue(self.ref_has_change(c_zref, B))
1969 self.assertTrue(self.ref_has_change(c_zref, C))
1970 self.assertFalse(self.ref_has_change(c_zref, D))
James E. Blair7d0dedc2013-02-21 17:26:09 -08001971
1972 # d ref should have a and b in 1, c and d in 2
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001973 self.assertTrue(self.ref_has_change(d_zref, A))
1974 self.assertTrue(self.ref_has_change(d_zref, B))
1975 self.assertTrue(self.ref_has_change(d_zref, C))
1976 self.assertTrue(self.ref_has_change(d_zref, D))
James E. Blair7d0dedc2013-02-21 17:26:09 -08001977
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001978 self.worker.hold_jobs_in_build = False
1979 self.worker.release()
James E. Blair7d0dedc2013-02-21 17:26:09 -08001980 self.waitUntilSettled()
1981
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001982 self.assertEqual(A.data['status'], 'MERGED')
1983 self.assertEqual(A.reported, 2)
1984 self.assertEqual(B.data['status'], 'MERGED')
1985 self.assertEqual(B.reported, 2)
1986 self.assertEqual(C.data['status'], 'MERGED')
1987 self.assertEqual(C.reported, 2)
1988 self.assertEqual(D.data['status'], 'MERGED')
1989 self.assertEqual(D.reported, 2)
James E. Blair70c71582013-03-06 08:50:50 -08001990
James E. Blair4a28a882013-08-23 15:17:33 -07001991 def test_rerun_on_error(self):
1992 "Test that if a worker fails to run a job, it is run again"
1993 self.worker.hold_jobs_in_build = True
1994 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1995 A.addApproval('CRVW', 2)
1996 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1997 self.waitUntilSettled()
1998
1999 self.builds[0].run_error = True
2000 self.worker.hold_jobs_in_build = False
2001 self.worker.release()
2002 self.waitUntilSettled()
2003 self.assertEqual(self.countJobResults(self.history, 'RUN_ERROR'), 1)
2004 self.assertEqual(self.countJobResults(self.history, 'SUCCESS'), 3)
2005
James E. Blair412e5582013-04-22 15:50:12 -07002006 def test_statsd(self):
2007 "Test each of the statsd methods used in the scheduler"
2008 import extras
2009 statsd = extras.try_import('statsd.statsd')
2010 statsd.incr('test-incr')
2011 statsd.timing('test-timing', 3)
Alex Gaynor813d39b2014-05-17 16:17:16 -07002012 statsd.gauge('test-gauge', 12)
James E. Blair412e5582013-04-22 15:50:12 -07002013 self.assertReportedStat('test-incr', '1|c')
2014 self.assertReportedStat('test-timing', '3|ms')
Alex Gaynor813d39b2014-05-17 16:17:16 -07002015 self.assertReportedStat('test-gauge', '12|g')
James E. Blair412e5582013-04-22 15:50:12 -07002016
James E. Blairdad52252014-02-07 16:59:17 -08002017 def test_stuck_job_cleanup(self):
2018 "Test that pending jobs are cleaned up if removed from layout"
James E. Blair18c64442014-03-18 10:14:45 -07002019 # This job won't be registered at startup because it is not in
2020 # the standard layout, but we need it to already be registerd
2021 # for when we reconfigure, as that is when Zuul will attempt
2022 # to run the new job.
2023 self.worker.registerFunction('build:gate-noop')
James E. Blairdad52252014-02-07 16:59:17 -08002024 self.gearman_server.hold_jobs_in_queue = True
2025 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2026 A.addApproval('CRVW', 2)
2027 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2028 self.waitUntilSettled()
2029 self.assertEqual(len(self.gearman_server.getQueue()), 1)
2030
2031 self.config.set('zuul', 'layout_config',
2032 'tests/fixtures/layout-no-jobs.yaml')
2033 self.sched.reconfigure(self.config)
2034 self.waitUntilSettled()
2035
James E. Blair18c64442014-03-18 10:14:45 -07002036 self.gearman_server.release('gate-noop')
James E. Blairdad52252014-02-07 16:59:17 -08002037 self.waitUntilSettled()
2038 self.assertEqual(len(self.gearman_server.getQueue()), 0)
2039 self.assertTrue(self.sched._areAllBuildsComplete())
2040
2041 self.assertEqual(len(self.history), 1)
James E. Blair18c64442014-03-18 10:14:45 -07002042 self.assertEqual(self.history[0].name, 'gate-noop')
James E. Blairdad52252014-02-07 16:59:17 -08002043 self.assertEqual(self.history[0].result, 'SUCCESS')
2044
James E. Blair879dafb2015-07-17 14:04:49 -07002045 def test_file_head(self):
2046 # This is a regression test for an observed bug. A change
2047 # with a file named "HEAD" in the root directory of the repo
2048 # was processed by a merger. It then was unable to reset the
2049 # repo because of:
2050 # GitCommandError: 'git reset --hard HEAD' returned
2051 # with exit code 128
2052 # stderr: 'fatal: ambiguous argument 'HEAD': both revision
2053 # and filename
2054 # Use '--' to separate filenames from revisions'
2055
2056 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2057 A.addPatchset(['HEAD'])
2058 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2059
2060 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
2061 self.waitUntilSettled()
2062
2063 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2064 self.waitUntilSettled()
2065
2066 self.assertIn('Build succeeded', A.messages[0])
2067 self.assertIn('Build succeeded', B.messages[0])
2068
James E. Blair70c71582013-03-06 08:50:50 -08002069 def test_file_jobs(self):
2070 "Test that file jobs run only when appropriate"
2071 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2072 A.addPatchset(['pip-requires'])
2073 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2074 A.addApproval('CRVW', 2)
2075 B.addApproval('CRVW', 2)
2076 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2077 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2078 self.waitUntilSettled()
2079
Monty Taylor6bef8ef2013-06-02 08:17:12 -04002080 testfile_jobs = [x for x in self.history
James E. Blair70c71582013-03-06 08:50:50 -08002081 if x.name == 'project-testfile']
2082
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002083 self.assertEqual(len(testfile_jobs), 1)
2084 self.assertEqual(testfile_jobs[0].changes, '1,2')
2085 self.assertEqual(A.data['status'], 'MERGED')
2086 self.assertEqual(A.reported, 2)
2087 self.assertEqual(B.data['status'], 'MERGED')
2088 self.assertEqual(B.reported, 2)
James E. Blair3c5e5b52013-04-26 11:17:03 -07002089
Maru Newby3fe5f852015-01-13 04:22:14 +00002090 def _test_skip_if_jobs(self, branch, should_skip):
2091 "Test that jobs with a skip-if filter run only when appropriate"
2092 self.config.set('zuul', 'layout_config',
2093 'tests/fixtures/layout-skip-if.yaml')
2094 self.sched.reconfigure(self.config)
2095 self.registerJobs()
2096
2097 change = self.fake_gerrit.addFakeChange('org/project',
2098 branch,
2099 'test skip-if')
2100 self.fake_gerrit.addEvent(change.getPatchsetCreatedEvent(1))
2101 self.waitUntilSettled()
2102
2103 tested_change_ids = [x.changes[0] for x in self.history
2104 if x.name == 'project-test-skip-if']
2105
2106 if should_skip:
2107 self.assertEqual([], tested_change_ids)
2108 else:
2109 self.assertIn(change.data['number'], tested_change_ids)
2110
2111 def test_skip_if_match_skips_job(self):
2112 self._test_skip_if_jobs(branch='master', should_skip=True)
2113
2114 def test_skip_if_no_match_runs_job(self):
2115 self._test_skip_if_jobs(branch='mp', should_skip=False)
2116
James E. Blair3c5e5b52013-04-26 11:17:03 -07002117 def test_test_config(self):
2118 "Test that we can test the config"
2119 sched = zuul.scheduler.Scheduler()
James E. Blair6c358e72013-07-29 17:06:47 -07002120 sched.registerTrigger(None, 'gerrit')
James E. Blair63bb0ef2013-07-29 17:14:51 -07002121 sched.registerTrigger(None, 'timer')
James E. Blairc494d542014-08-06 09:23:52 -07002122 sched.registerTrigger(None, 'zuul')
Clark Boylanb640e052014-04-03 16:41:46 -07002123 sched.testConfig(self.config.get('zuul', 'layout_config'))
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002124
2125 def test_build_description(self):
2126 "Test that build descriptions update"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002127 self.worker.registerFunction('set_description:' +
2128 self.worker.worker_id)
2129
2130 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2131 A.addApproval('CRVW', 2)
2132 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2133 self.waitUntilSettled()
Monty Taylor6bef8ef2013-06-02 08:17:12 -04002134 desc = self.history[0].description
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002135 self.log.debug("Description: %s" % desc)
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002136 self.assertTrue(re.search("Branch.*master", desc))
2137 self.assertTrue(re.search("Pipeline.*gate", desc))
2138 self.assertTrue(re.search("project-merge.*SUCCESS", desc))
2139 self.assertTrue(re.search("project-test1.*SUCCESS", desc))
2140 self.assertTrue(re.search("project-test2.*SUCCESS", desc))
2141 self.assertTrue(re.search("Reported result.*SUCCESS", desc))
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002142
James E. Blairc8a1e052014-02-25 09:29:26 -08002143 def test_queue_names(self):
2144 "Test shared change queue names"
2145 project1 = self.sched.layout.projects['org/project1']
2146 project2 = self.sched.layout.projects['org/project2']
2147 q1 = self.sched.layout.pipelines['gate'].getQueue(project1)
2148 q2 = self.sched.layout.pipelines['gate'].getQueue(project2)
2149 self.assertEqual(q1.name, 'integration')
2150 self.assertEqual(q2.name, 'integration')
2151
2152 self.config.set('zuul', 'layout_config',
2153 'tests/fixtures/layout-bad-queue.yaml')
2154 with testtools.ExpectedException(
2155 Exception, "More than one name assigned to change queue"):
2156 self.sched.reconfigure(self.config)
2157
James E. Blair64ed6f22013-07-10 14:07:23 -07002158 def test_queue_precedence(self):
2159 "Test that queue precedence works"
2160
2161 self.gearman_server.hold_jobs_in_queue = True
James E. Blair8de58bd2013-07-18 16:23:33 -07002162 self.worker.hold_jobs_in_build = True
James E. Blair64ed6f22013-07-10 14:07:23 -07002163 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2164 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2165 A.addApproval('CRVW', 2)
2166 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2167
2168 self.waitUntilSettled()
2169 self.gearman_server.hold_jobs_in_queue = False
2170 self.gearman_server.release()
2171 self.waitUntilSettled()
2172
James E. Blair8de58bd2013-07-18 16:23:33 -07002173 # Run one build at a time to ensure non-race order:
James E. Blairb8c16472015-05-05 14:55:26 -07002174 self.orderedRelease()
James E. Blair8de58bd2013-07-18 16:23:33 -07002175 self.worker.hold_jobs_in_build = False
2176 self.waitUntilSettled()
2177
James E. Blair64ed6f22013-07-10 14:07:23 -07002178 self.log.debug(self.history)
2179 self.assertEqual(self.history[0].pipeline, 'gate')
2180 self.assertEqual(self.history[1].pipeline, 'check')
2181 self.assertEqual(self.history[2].pipeline, 'gate')
2182 self.assertEqual(self.history[3].pipeline, 'gate')
2183 self.assertEqual(self.history[4].pipeline, 'check')
2184 self.assertEqual(self.history[5].pipeline, 'check')
2185
Clark Boylana5edbe42014-06-03 16:39:10 -07002186 def test_json_status(self):
James E. Blair1843a552013-07-03 14:19:52 -07002187 "Test that we can retrieve JSON status info"
2188 self.worker.hold_jobs_in_build = True
2189 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2190 A.addApproval('CRVW', 2)
2191 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2192 self.waitUntilSettled()
2193
2194 port = self.webapp.server.socket.getsockname()[1]
2195
Yuriy Taradaya6d452f2014-04-16 12:36:20 +04002196 req = urllib2.Request("http://localhost:%s/status.json" % port)
Yuriy Taradaya6d452f2014-04-16 12:36:20 +04002197 f = urllib2.urlopen(req)
Clark Boylanaa4f2e72014-06-03 21:22:40 -07002198 headers = f.info()
2199 self.assertIn('Content-Length', headers)
2200 self.assertIn('Content-Type', headers)
2201 self.assertEqual(headers['Content-Type'],
2202 'application/json; charset=UTF-8')
Timo Tijhof0ebd2932015-04-02 12:11:21 +01002203 self.assertIn('Access-Control-Allow-Origin', headers)
2204 self.assertIn('Cache-Control', headers)
Clark Boylanaa4f2e72014-06-03 21:22:40 -07002205 self.assertIn('Last-Modified', headers)
Timo Tijhof0ebd2932015-04-02 12:11:21 +01002206 self.assertIn('Expires', headers)
James E. Blair1843a552013-07-03 14:19:52 -07002207 data = f.read()
2208
2209 self.worker.hold_jobs_in_build = False
2210 self.worker.release()
2211 self.waitUntilSettled()
2212
2213 data = json.loads(data)
2214 status_jobs = set()
2215 for p in data['pipelines']:
2216 for q in p['change_queues']:
James E. Blairbfb8e042014-12-30 17:01:44 -08002217 if p['name'] in ['gate', 'conflict']:
Clark Boylanaf2476f2014-01-23 14:47:36 -08002218 self.assertEqual(q['window'], 20)
2219 else:
2220 self.assertEqual(q['window'], 0)
James E. Blair1843a552013-07-03 14:19:52 -07002221 for head in q['heads']:
2222 for change in head:
Clark Boylanaf2476f2014-01-23 14:47:36 -08002223 self.assertTrue(change['active'])
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002224 self.assertEqual(change['id'], '1,1')
James E. Blair1843a552013-07-03 14:19:52 -07002225 for job in change['jobs']:
2226 status_jobs.add(job['name'])
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002227 self.assertIn('project-merge', status_jobs)
2228 self.assertIn('project-test1', status_jobs)
2229 self.assertIn('project-test2', status_jobs)
James E. Blair1843a552013-07-03 14:19:52 -07002230
James E. Blairc3d428e2013-12-03 15:06:48 -08002231 def test_merging_queues(self):
2232 "Test that transitively-connected change queues are merged"
2233 self.config.set('zuul', 'layout_config',
2234 'tests/fixtures/layout-merge-queues.yaml')
2235 self.sched.reconfigure(self.config)
2236 self.assertEqual(len(self.sched.layout.pipelines['gate'].queues), 1)
2237
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002238 def test_node_label(self):
2239 "Test that a job runs on a specific node label"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002240 self.worker.registerFunction('build:node-project-test1:debian')
2241
2242 A = self.fake_gerrit.addFakeChange('org/node-project', 'master', 'A')
2243 A.addApproval('CRVW', 2)
2244 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2245 self.waitUntilSettled()
James E. Blair4ca985f2013-05-30 12:27:43 -07002246
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002247 self.assertIsNone(self.getJobFromHistory('node-project-merge').node)
2248 self.assertEqual(self.getJobFromHistory('node-project-test1').node,
2249 'debian')
2250 self.assertIsNone(self.getJobFromHistory('node-project-test2').node)
James E. Blaircdccd972013-07-01 12:10:22 -07002251
2252 def test_live_reconfiguration(self):
2253 "Test that live reconfiguration works"
2254 self.worker.hold_jobs_in_build = True
2255 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2256 A.addApproval('CRVW', 2)
2257 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2258 self.waitUntilSettled()
2259
2260 self.sched.reconfigure(self.config)
2261
2262 self.worker.hold_jobs_in_build = False
2263 self.worker.release()
2264 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002265 self.assertEqual(self.getJobFromHistory('project-merge').result,
2266 'SUCCESS')
2267 self.assertEqual(self.getJobFromHistory('project-test1').result,
2268 'SUCCESS')
2269 self.assertEqual(self.getJobFromHistory('project-test2').result,
2270 'SUCCESS')
2271 self.assertEqual(A.data['status'], 'MERGED')
2272 self.assertEqual(A.reported, 2)
James E. Blair287c06d2013-07-24 10:39:30 -07002273
James E. Blair6bc782d2015-07-17 16:20:21 -07002274 def test_live_reconfiguration_merge_conflict(self):
2275 # A real-world bug: a change in a gate queue has a merge
2276 # conflict and a job is added to its project while it's
2277 # sitting in the queue. The job gets added to the change and
2278 # enqueued and the change gets stuck.
2279 self.worker.registerFunction('build:project-test3')
2280 self.worker.hold_jobs_in_build = True
2281
2282 # This change is fine. It's here to stop the queue long
2283 # enough for the next change to be subject to the
2284 # reconfiguration, as well as to provide a conflict for the
2285 # next change. This change will succeed and merge.
2286 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2287 A.addPatchset(['conflict'])
2288 A.addApproval('CRVW', 2)
James E. Blair6bc782d2015-07-17 16:20:21 -07002289
2290 # This change will be in merge conflict. During the
2291 # reconfiguration, we will add a job. We want to make sure
2292 # that doesn't cause it to get stuck.
2293 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2294 B.addPatchset(['conflict'])
2295 B.addApproval('CRVW', 2)
James E. Blair4eb21fa2015-07-27 14:56:47 -07002296
2297 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
James E. Blair6bc782d2015-07-17 16:20:21 -07002298 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2299
2300 self.waitUntilSettled()
2301
2302 # No jobs have run yet
2303 self.assertEqual(A.data['status'], 'NEW')
2304 self.assertEqual(A.reported, 1)
2305 self.assertEqual(B.data['status'], 'NEW')
2306 self.assertEqual(B.reported, 1)
2307 self.assertEqual(len(self.history), 0)
2308
2309 # Add the "project-test3" job.
2310 self.config.set('zuul', 'layout_config',
2311 'tests/fixtures/layout-live-'
2312 'reconfiguration-add-job.yaml')
2313 self.sched.reconfigure(self.config)
2314 self.waitUntilSettled()
2315
2316 self.worker.hold_jobs_in_build = False
2317 self.worker.release()
2318 self.waitUntilSettled()
2319
2320 self.assertEqual(A.data['status'], 'MERGED')
2321 self.assertEqual(A.reported, 2)
2322 self.assertEqual(B.data['status'], 'NEW')
2323 self.assertEqual(B.reported, 2)
2324 self.assertEqual(self.getJobFromHistory('project-merge').result,
2325 'SUCCESS')
2326 self.assertEqual(self.getJobFromHistory('project-test1').result,
2327 'SUCCESS')
2328 self.assertEqual(self.getJobFromHistory('project-test2').result,
2329 'SUCCESS')
2330 self.assertEqual(self.getJobFromHistory('project-test3').result,
2331 'SUCCESS')
2332 self.assertEqual(len(self.history), 4)
2333
James E. Blair400e8fd2015-07-30 17:44:45 -07002334 def test_live_reconfiguration_failed_root(self):
James E. Blair6bc782d2015-07-17 16:20:21 -07002335 # An extrapolation of test_live_reconfiguration_merge_conflict
2336 # that tests a job added to a job tree with a failed root does
2337 # not run.
2338 self.worker.registerFunction('build:project-test3')
2339 self.worker.hold_jobs_in_build = True
2340
2341 # This change is fine. It's here to stop the queue long
2342 # enough for the next change to be subject to the
2343 # reconfiguration. This change will succeed and merge.
2344 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2345 A.addPatchset(['conflict'])
2346 A.addApproval('CRVW', 2)
2347 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2348 self.waitUntilSettled()
2349 self.worker.release('.*-merge')
2350 self.waitUntilSettled()
2351
2352 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2353 self.worker.addFailTest('project-merge', B)
2354 B.addApproval('CRVW', 2)
2355 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2356 self.waitUntilSettled()
2357
2358 self.worker.release('.*-merge')
2359 self.waitUntilSettled()
2360
2361 # Both -merge jobs have run, but no others.
2362 self.assertEqual(A.data['status'], 'NEW')
2363 self.assertEqual(A.reported, 1)
2364 self.assertEqual(B.data['status'], 'NEW')
2365 self.assertEqual(B.reported, 1)
2366 self.assertEqual(self.history[0].result, 'SUCCESS')
2367 self.assertEqual(self.history[0].name, 'project-merge')
2368 self.assertEqual(self.history[1].result, 'FAILURE')
2369 self.assertEqual(self.history[1].name, 'project-merge')
2370 self.assertEqual(len(self.history), 2)
2371
2372 # Add the "project-test3" job.
2373 self.config.set('zuul', 'layout_config',
2374 'tests/fixtures/layout-live-'
2375 'reconfiguration-add-job.yaml')
2376 self.sched.reconfigure(self.config)
2377 self.waitUntilSettled()
2378
2379 self.worker.hold_jobs_in_build = False
2380 self.worker.release()
2381 self.waitUntilSettled()
2382
2383 self.assertEqual(A.data['status'], 'MERGED')
2384 self.assertEqual(A.reported, 2)
2385 self.assertEqual(B.data['status'], 'NEW')
2386 self.assertEqual(B.reported, 2)
2387 self.assertEqual(self.history[0].result, 'SUCCESS')
2388 self.assertEqual(self.history[0].name, 'project-merge')
2389 self.assertEqual(self.history[1].result, 'FAILURE')
2390 self.assertEqual(self.history[1].name, 'project-merge')
2391 self.assertEqual(self.history[2].result, 'SUCCESS')
2392 self.assertEqual(self.history[3].result, 'SUCCESS')
2393 self.assertEqual(self.history[4].result, 'SUCCESS')
2394 self.assertEqual(len(self.history), 5)
2395
James E. Blair400e8fd2015-07-30 17:44:45 -07002396 def test_live_reconfiguration_failed_job(self):
2397 # Test that a change with a removed failing job does not
2398 # disrupt reconfiguration. If a change has a failed job and
2399 # that job is removed during a reconfiguration, we observed a
2400 # bug where the code to re-set build statuses would run on
2401 # that build and raise an exception because the job no longer
2402 # existed.
2403 self.worker.hold_jobs_in_build = True
2404
2405 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2406
2407 # This change will fail and later be removed by the reconfiguration.
2408 self.worker.addFailTest('project-test1', A)
2409
2410 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2411 self.waitUntilSettled()
2412 self.worker.release('.*-merge')
2413 self.waitUntilSettled()
2414 self.worker.release('project-test1')
2415 self.waitUntilSettled()
2416
2417 self.assertEqual(A.data['status'], 'NEW')
2418 self.assertEqual(A.reported, 0)
2419
2420 self.assertEqual(self.getJobFromHistory('project-merge').result,
2421 'SUCCESS')
2422 self.assertEqual(self.getJobFromHistory('project-test1').result,
2423 'FAILURE')
2424 self.assertEqual(len(self.history), 2)
2425
2426 # Remove the test1 job.
2427 self.config.set('zuul', 'layout_config',
2428 'tests/fixtures/layout-live-'
2429 'reconfiguration-failed-job.yaml')
2430 self.sched.reconfigure(self.config)
2431 self.waitUntilSettled()
2432
2433 self.worker.hold_jobs_in_build = False
2434 self.worker.release()
2435 self.waitUntilSettled()
2436
2437 self.assertEqual(self.getJobFromHistory('project-test2').result,
2438 'SUCCESS')
2439 self.assertEqual(self.getJobFromHistory('project-testfile').result,
2440 'SUCCESS')
2441 self.assertEqual(len(self.history), 4)
2442
2443 self.assertEqual(A.data['status'], 'NEW')
2444 self.assertEqual(A.reported, 1)
2445 self.assertIn('Build succeeded', A.messages[0])
2446 # Ensure the removed job was not included in the report.
2447 self.assertNotIn('project-test1', A.messages[0])
2448
James E. Blairfe707d12015-08-05 15:18:15 -07002449 def test_live_reconfiguration_shared_queue(self):
2450 # Test that a change with a failing job which was removed from
2451 # this project but otherwise still exists in the system does
2452 # not disrupt reconfiguration.
2453
2454 self.worker.hold_jobs_in_build = True
2455
2456 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
2457
2458 self.worker.addFailTest('project1-project2-integration', A)
2459
2460 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2461 self.waitUntilSettled()
2462 self.worker.release('.*-merge')
2463 self.waitUntilSettled()
2464 self.worker.release('project1-project2-integration')
2465 self.waitUntilSettled()
2466
2467 self.assertEqual(A.data['status'], 'NEW')
2468 self.assertEqual(A.reported, 0)
2469
2470 self.assertEqual(self.getJobFromHistory('project1-merge').result,
2471 'SUCCESS')
2472 self.assertEqual(self.getJobFromHistory(
2473 'project1-project2-integration').result, 'FAILURE')
2474 self.assertEqual(len(self.history), 2)
2475
2476 # Remove the integration job.
2477 self.config.set('zuul', 'layout_config',
2478 'tests/fixtures/layout-live-'
2479 'reconfiguration-shared-queue.yaml')
2480 self.sched.reconfigure(self.config)
2481 self.waitUntilSettled()
2482
2483 self.worker.hold_jobs_in_build = False
2484 self.worker.release()
2485 self.waitUntilSettled()
2486
2487 self.assertEqual(self.getJobFromHistory('project1-merge').result,
2488 'SUCCESS')
2489 self.assertEqual(self.getJobFromHistory('project1-test1').result,
2490 'SUCCESS')
2491 self.assertEqual(self.getJobFromHistory('project1-test2').result,
2492 'SUCCESS')
2493 self.assertEqual(self.getJobFromHistory(
2494 'project1-project2-integration').result, 'FAILURE')
2495 self.assertEqual(len(self.history), 4)
2496
2497 self.assertEqual(A.data['status'], 'NEW')
2498 self.assertEqual(A.reported, 1)
2499 self.assertIn('Build succeeded', A.messages[0])
2500 # Ensure the removed job was not included in the report.
2501 self.assertNotIn('project1-project2-integration', A.messages[0])
2502
Evgeny Antyshev0deaaad2015-08-03 20:22:56 +00002503 def test_live_reconfiguration_del_project(self):
2504 # Test project deletion from layout
2505 # while changes are enqueued
2506
2507 self.worker.hold_jobs_in_build = True
2508 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2509 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
2510 C = self.fake_gerrit.addFakeChange('org/project1', 'master', 'C')
2511
2512 # A Depends-On: B
2513 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
2514 A.subject, B.data['id'])
2515 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2516
2517 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2518 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
2519 self.waitUntilSettled()
2520 self.worker.release('.*-merge')
2521 self.waitUntilSettled()
2522 self.assertEqual(len(self.builds), 5)
2523
2524 # This layout defines only org/project, not org/project1
2525 self.config.set('zuul', 'layout_config',
2526 'tests/fixtures/layout-live-'
2527 'reconfiguration-del-project.yaml')
2528 self.sched.reconfigure(self.config)
2529 self.waitUntilSettled()
2530
2531 # Builds for C aborted, builds for A succeed,
2532 # and have change B applied ahead
2533 job_c = self.getJobFromHistory('project1-test1')
2534 self.assertEqual(job_c.changes, '3,1')
2535 self.assertEqual(job_c.result, 'ABORTED')
2536
2537 self.worker.hold_jobs_in_build = False
2538 self.worker.release()
2539 self.waitUntilSettled()
2540
2541 self.assertEqual(self.getJobFromHistory('project-test1').changes,
2542 '2,1 1,1')
2543
2544 self.assertEqual(A.data['status'], 'NEW')
2545 self.assertEqual(B.data['status'], 'NEW')
2546 self.assertEqual(C.data['status'], 'NEW')
2547 self.assertEqual(A.reported, 1)
2548 self.assertEqual(B.reported, 0)
2549 self.assertEqual(C.reported, 0)
2550
2551 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 0)
2552 self.assertIn('Build succeeded', A.messages[0])
2553
James E. Blaire712d9f2013-07-31 11:40:11 -07002554 def test_live_reconfiguration_functions(self):
2555 "Test live reconfiguration with a custom function"
2556 self.worker.registerFunction('build:node-project-test1:debian')
2557 self.worker.registerFunction('build:node-project-test1:wheezy')
2558 A = self.fake_gerrit.addFakeChange('org/node-project', 'master', 'A')
2559 A.addApproval('CRVW', 2)
2560 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2561 self.waitUntilSettled()
2562
2563 self.assertIsNone(self.getJobFromHistory('node-project-merge').node)
2564 self.assertEqual(self.getJobFromHistory('node-project-test1').node,
2565 'debian')
2566 self.assertIsNone(self.getJobFromHistory('node-project-test2').node)
2567
2568 self.config.set('zuul', 'layout_config',
2569 'tests/fixtures/layout-live-'
2570 'reconfiguration-functions.yaml')
2571 self.sched.reconfigure(self.config)
2572 self.worker.build_history = []
2573
2574 B = self.fake_gerrit.addFakeChange('org/node-project', 'master', 'B')
2575 B.addApproval('CRVW', 2)
2576 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2577 self.waitUntilSettled()
2578
2579 self.assertIsNone(self.getJobFromHistory('node-project-merge').node)
2580 self.assertEqual(self.getJobFromHistory('node-project-test1').node,
2581 'wheezy')
2582 self.assertIsNone(self.getJobFromHistory('node-project-test2').node)
2583
James E. Blair287c06d2013-07-24 10:39:30 -07002584 def test_delayed_repo_init(self):
2585 self.config.set('zuul', 'layout_config',
2586 'tests/fixtures/layout-delayed-repo-init.yaml')
2587 self.sched.reconfigure(self.config)
2588
2589 self.init_repo("org/new-project")
2590 A = self.fake_gerrit.addFakeChange('org/new-project', 'master', 'A')
2591
2592 A.addApproval('CRVW', 2)
2593 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2594 self.waitUntilSettled()
2595 self.assertEqual(self.getJobFromHistory('project-merge').result,
2596 'SUCCESS')
2597 self.assertEqual(self.getJobFromHistory('project-test1').result,
2598 'SUCCESS')
2599 self.assertEqual(self.getJobFromHistory('project-test2').result,
2600 'SUCCESS')
2601 self.assertEqual(A.data['status'], 'MERGED')
2602 self.assertEqual(A.reported, 2)
James E. Blair63bb0ef2013-07-29 17:14:51 -07002603
Clark Boylan6dbbc482013-10-18 10:57:31 -07002604 def test_repo_deleted(self):
2605 self.config.set('zuul', 'layout_config',
2606 'tests/fixtures/layout-repo-deleted.yaml')
2607 self.sched.reconfigure(self.config)
2608
2609 self.init_repo("org/delete-project")
2610 A = self.fake_gerrit.addFakeChange('org/delete-project', 'master', 'A')
2611
2612 A.addApproval('CRVW', 2)
2613 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2614 self.waitUntilSettled()
2615 self.assertEqual(self.getJobFromHistory('project-merge').result,
2616 'SUCCESS')
2617 self.assertEqual(self.getJobFromHistory('project-test1').result,
2618 'SUCCESS')
2619 self.assertEqual(self.getJobFromHistory('project-test2').result,
2620 'SUCCESS')
2621 self.assertEqual(A.data['status'], 'MERGED')
2622 self.assertEqual(A.reported, 2)
2623
2624 # Delete org/new-project zuul repo. Should be recloned.
2625 shutil.rmtree(os.path.join(self.git_root, "org/delete-project"))
2626
2627 B = self.fake_gerrit.addFakeChange('org/delete-project', 'master', 'B')
2628
2629 B.addApproval('CRVW', 2)
2630 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2631 self.waitUntilSettled()
2632 self.assertEqual(self.getJobFromHistory('project-merge').result,
2633 'SUCCESS')
2634 self.assertEqual(self.getJobFromHistory('project-test1').result,
2635 'SUCCESS')
2636 self.assertEqual(self.getJobFromHistory('project-test2').result,
2637 'SUCCESS')
2638 self.assertEqual(B.data['status'], 'MERGED')
2639 self.assertEqual(B.reported, 2)
2640
James E. Blair63bb0ef2013-07-29 17:14:51 -07002641 def test_timer(self):
2642 "Test that a periodic job is triggered"
2643 self.worker.hold_jobs_in_build = True
2644 self.config.set('zuul', 'layout_config',
2645 'tests/fixtures/layout-timer.yaml')
2646 self.sched.reconfigure(self.config)
2647 self.registerJobs()
2648
Clark Boylan3ee090a2014-04-03 20:55:09 -07002649 # The pipeline triggers every second, so we should have seen
2650 # several by now.
2651 time.sleep(5)
James E. Blair63bb0ef2013-07-29 17:14:51 -07002652 self.waitUntilSettled()
Clark Boylan3ee090a2014-04-03 20:55:09 -07002653
2654 self.assertEqual(len(self.builds), 2)
2655
James E. Blair63bb0ef2013-07-29 17:14:51 -07002656 port = self.webapp.server.socket.getsockname()[1]
2657
2658 f = urllib.urlopen("http://localhost:%s/status.json" % port)
2659 data = f.read()
2660
2661 self.worker.hold_jobs_in_build = False
Clark Boylan3ee090a2014-04-03 20:55:09 -07002662 # Stop queuing timer triggered jobs so that the assertions
2663 # below don't race against more jobs being queued.
2664 self.config.set('zuul', 'layout_config',
2665 'tests/fixtures/layout-no-timer.yaml')
2666 self.sched.reconfigure(self.config)
2667 self.registerJobs()
James E. Blair63bb0ef2013-07-29 17:14:51 -07002668 self.worker.release()
2669 self.waitUntilSettled()
2670
2671 self.assertEqual(self.getJobFromHistory(
2672 'project-bitrot-stable-old').result, 'SUCCESS')
2673 self.assertEqual(self.getJobFromHistory(
2674 'project-bitrot-stable-older').result, 'SUCCESS')
2675
2676 data = json.loads(data)
2677 status_jobs = set()
2678 for p in data['pipelines']:
2679 for q in p['change_queues']:
2680 for head in q['heads']:
2681 for change in head:
Alex Gaynorddb9ef32013-09-16 21:04:58 -07002682 self.assertEqual(change['id'], None)
James E. Blair63bb0ef2013-07-29 17:14:51 -07002683 for job in change['jobs']:
2684 status_jobs.add(job['name'])
2685 self.assertIn('project-bitrot-stable-old', status_jobs)
2686 self.assertIn('project-bitrot-stable-older', status_jobs)
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002687
James E. Blair4f6033c2014-03-27 15:49:09 -07002688 def test_idle(self):
2689 "Test that frequent periodic jobs work"
2690 self.worker.hold_jobs_in_build = True
James E. Blair4f6033c2014-03-27 15:49:09 -07002691
Clark Boylan3ee090a2014-04-03 20:55:09 -07002692 for x in range(1, 3):
2693 # Test that timer triggers periodic jobs even across
2694 # layout config reloads.
2695 # Start timer trigger
2696 self.config.set('zuul', 'layout_config',
2697 'tests/fixtures/layout-idle.yaml')
2698 self.sched.reconfigure(self.config)
2699 self.registerJobs()
James E. Blair4f6033c2014-03-27 15:49:09 -07002700
Clark Boylan3ee090a2014-04-03 20:55:09 -07002701 # The pipeline triggers every second, so we should have seen
2702 # several by now.
2703 time.sleep(5)
2704 self.waitUntilSettled()
2705
2706 # Stop queuing timer triggered jobs so that the assertions
2707 # below don't race against more jobs being queued.
2708 self.config.set('zuul', 'layout_config',
2709 'tests/fixtures/layout-no-timer.yaml')
2710 self.sched.reconfigure(self.config)
2711 self.registerJobs()
2712
2713 self.assertEqual(len(self.builds), 2)
2714 self.worker.release('.*')
2715 self.waitUntilSettled()
2716 self.assertEqual(len(self.builds), 0)
2717 self.assertEqual(len(self.history), x * 2)
James E. Blair4f6033c2014-03-27 15:49:09 -07002718
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002719 def test_check_smtp_pool(self):
2720 self.config.set('zuul', 'layout_config',
2721 'tests/fixtures/layout-smtp.yaml')
2722 self.sched.reconfigure(self.config)
2723
2724 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2725 self.waitUntilSettled()
2726
2727 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2728 self.waitUntilSettled()
2729
James E. Blairff80a2f2013-12-27 13:24:06 -08002730 self.assertEqual(len(self.smtp_messages), 2)
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002731
2732 # A.messages only holds what FakeGerrit places in it. Thus we
2733 # work on the knowledge of what the first message should be as
2734 # it is only configured to go to SMTP.
2735
2736 self.assertEqual('zuul@example.com',
James E. Blairff80a2f2013-12-27 13:24:06 -08002737 self.smtp_messages[0]['from_email'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002738 self.assertEqual(['you@example.com'],
James E. Blairff80a2f2013-12-27 13:24:06 -08002739 self.smtp_messages[0]['to_email'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002740 self.assertEqual('Starting check jobs.',
James E. Blairff80a2f2013-12-27 13:24:06 -08002741 self.smtp_messages[0]['body'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002742
2743 self.assertEqual('zuul_from@example.com',
James E. Blairff80a2f2013-12-27 13:24:06 -08002744 self.smtp_messages[1]['from_email'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002745 self.assertEqual(['alternative_me@example.com'],
James E. Blairff80a2f2013-12-27 13:24:06 -08002746 self.smtp_messages[1]['to_email'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002747 self.assertEqual(A.messages[0],
James E. Blairff80a2f2013-12-27 13:24:06 -08002748 self.smtp_messages[1]['body'])
James E. Blairad28e912013-11-27 10:43:22 -08002749
James E. Blaire5910202013-12-27 09:50:31 -08002750 def test_timer_smtp(self):
2751 "Test that a periodic job is triggered"
Clark Boylan3ee090a2014-04-03 20:55:09 -07002752 self.worker.hold_jobs_in_build = True
James E. Blaire5910202013-12-27 09:50:31 -08002753 self.config.set('zuul', 'layout_config',
2754 'tests/fixtures/layout-timer-smtp.yaml')
2755 self.sched.reconfigure(self.config)
2756 self.registerJobs()
2757
Clark Boylan3ee090a2014-04-03 20:55:09 -07002758 # The pipeline triggers every second, so we should have seen
2759 # several by now.
2760 time.sleep(5)
James E. Blaire5910202013-12-27 09:50:31 -08002761 self.waitUntilSettled()
2762
Clark Boylan3ee090a2014-04-03 20:55:09 -07002763 self.assertEqual(len(self.builds), 2)
2764 self.worker.release('.*')
2765 self.waitUntilSettled()
2766 self.assertEqual(len(self.history), 2)
2767
James E. Blaire5910202013-12-27 09:50:31 -08002768 self.assertEqual(self.getJobFromHistory(
2769 'project-bitrot-stable-old').result, 'SUCCESS')
2770 self.assertEqual(self.getJobFromHistory(
2771 'project-bitrot-stable-older').result, 'SUCCESS')
2772
James E. Blairff80a2f2013-12-27 13:24:06 -08002773 self.assertEqual(len(self.smtp_messages), 1)
James E. Blaire5910202013-12-27 09:50:31 -08002774
2775 # A.messages only holds what FakeGerrit places in it. Thus we
2776 # work on the knowledge of what the first message should be as
2777 # it is only configured to go to SMTP.
2778
2779 self.assertEqual('zuul_from@example.com',
James E. Blairff80a2f2013-12-27 13:24:06 -08002780 self.smtp_messages[0]['from_email'])
James E. Blaire5910202013-12-27 09:50:31 -08002781 self.assertEqual(['alternative_me@example.com'],
James E. Blairff80a2f2013-12-27 13:24:06 -08002782 self.smtp_messages[0]['to_email'])
James E. Blaire5910202013-12-27 09:50:31 -08002783 self.assertIn('Subject: Periodic check for org/project succeeded',
James E. Blairff80a2f2013-12-27 13:24:06 -08002784 self.smtp_messages[0]['headers'])
James E. Blaire5910202013-12-27 09:50:31 -08002785
Clark Boylan3ee090a2014-04-03 20:55:09 -07002786 # Stop queuing timer triggered jobs and let any that may have
2787 # queued through so that end of test assertions pass.
2788 self.config.set('zuul', 'layout_config',
2789 'tests/fixtures/layout-no-timer.yaml')
2790 self.sched.reconfigure(self.config)
2791 self.registerJobs()
James E. Blairf8058972014-08-15 16:09:16 -07002792 self.waitUntilSettled()
Clark Boylan3ee090a2014-04-03 20:55:09 -07002793 self.worker.release('.*')
2794 self.waitUntilSettled()
2795
James E. Blair91e34592015-07-31 16:45:59 -07002796 def test_client_enqueue_change(self):
James E. Blairad28e912013-11-27 10:43:22 -08002797 "Test that the RPC client can enqueue a change"
2798 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2799 A.addApproval('CRVW', 2)
2800 A.addApproval('APRV', 1)
2801
2802 client = zuul.rpcclient.RPCClient('127.0.0.1',
2803 self.gearman_server.port)
2804 r = client.enqueue(pipeline='gate',
2805 project='org/project',
2806 trigger='gerrit',
James E. Blair36658cf2013-12-06 17:53:48 -08002807 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08002808 self.waitUntilSettled()
2809 self.assertEqual(self.getJobFromHistory('project-merge').result,
2810 'SUCCESS')
2811 self.assertEqual(self.getJobFromHistory('project-test1').result,
2812 'SUCCESS')
2813 self.assertEqual(self.getJobFromHistory('project-test2').result,
2814 'SUCCESS')
2815 self.assertEqual(A.data['status'], 'MERGED')
2816 self.assertEqual(A.reported, 2)
2817 self.assertEqual(r, True)
2818
James E. Blair91e34592015-07-31 16:45:59 -07002819 def test_client_enqueue_ref(self):
2820 "Test that the RPC client can enqueue a ref"
2821
2822 client = zuul.rpcclient.RPCClient('127.0.0.1',
2823 self.gearman_server.port)
2824 r = client.enqueue_ref(
2825 pipeline='post',
2826 project='org/project',
2827 trigger='gerrit',
2828 ref='master',
2829 oldrev='90f173846e3af9154517b88543ffbd1691f31366',
2830 newrev='d479a0bfcb34da57a31adb2a595c0cf687812543')
2831 self.waitUntilSettled()
2832 job_names = [x.name for x in self.history]
2833 self.assertEqual(len(self.history), 1)
2834 self.assertIn('project-post', job_names)
2835 self.assertEqual(r, True)
2836
James E. Blairad28e912013-11-27 10:43:22 -08002837 def test_client_enqueue_negative(self):
2838 "Test that the RPC client returns errors"
2839 client = zuul.rpcclient.RPCClient('127.0.0.1',
2840 self.gearman_server.port)
2841 with testtools.ExpectedException(zuul.rpcclient.RPCFailure,
2842 "Invalid project"):
2843 r = client.enqueue(pipeline='gate',
2844 project='project-does-not-exist',
2845 trigger='gerrit',
James E. Blair36658cf2013-12-06 17:53:48 -08002846 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08002847 client.shutdown()
2848 self.assertEqual(r, False)
2849
2850 with testtools.ExpectedException(zuul.rpcclient.RPCFailure,
2851 "Invalid pipeline"):
2852 r = client.enqueue(pipeline='pipeline-does-not-exist',
2853 project='org/project',
2854 trigger='gerrit',
James E. Blair36658cf2013-12-06 17:53:48 -08002855 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08002856 client.shutdown()
2857 self.assertEqual(r, False)
2858
2859 with testtools.ExpectedException(zuul.rpcclient.RPCFailure,
2860 "Invalid trigger"):
2861 r = client.enqueue(pipeline='gate',
2862 project='org/project',
2863 trigger='trigger-does-not-exist',
James E. Blair36658cf2013-12-06 17:53:48 -08002864 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08002865 client.shutdown()
2866 self.assertEqual(r, False)
2867
2868 with testtools.ExpectedException(zuul.rpcclient.RPCFailure,
2869 "Invalid change"):
2870 r = client.enqueue(pipeline='gate',
2871 project='org/project',
2872 trigger='gerrit',
James E. Blair36658cf2013-12-06 17:53:48 -08002873 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08002874 client.shutdown()
2875 self.assertEqual(r, False)
2876
2877 self.waitUntilSettled()
2878 self.assertEqual(len(self.history), 0)
2879 self.assertEqual(len(self.builds), 0)
James E. Blair36658cf2013-12-06 17:53:48 -08002880
2881 def test_client_promote(self):
2882 "Test that the RPC client can promote a change"
2883 self.worker.hold_jobs_in_build = True
2884 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2885 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2886 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
2887 A.addApproval('CRVW', 2)
2888 B.addApproval('CRVW', 2)
2889 C.addApproval('CRVW', 2)
2890
2891 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2892 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2893 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
2894
2895 self.waitUntilSettled()
2896
Sean Daguef39b9ca2014-01-10 21:34:35 -05002897 items = self.sched.layout.pipelines['gate'].getAllItems()
2898 enqueue_times = {}
2899 for item in items:
2900 enqueue_times[str(item.change)] = item.enqueue_time
2901
James E. Blair36658cf2013-12-06 17:53:48 -08002902 client = zuul.rpcclient.RPCClient('127.0.0.1',
2903 self.gearman_server.port)
2904 r = client.promote(pipeline='gate',
2905 change_ids=['2,1', '3,1'])
2906
Sean Daguef39b9ca2014-01-10 21:34:35 -05002907 # ensure that enqueue times are durable
2908 items = self.sched.layout.pipelines['gate'].getAllItems()
2909 for item in items:
2910 self.assertEqual(
2911 enqueue_times[str(item.change)], item.enqueue_time)
2912
James E. Blair78acec92014-02-06 07:11:32 -08002913 self.waitUntilSettled()
James E. Blair36658cf2013-12-06 17:53:48 -08002914 self.worker.release('.*-merge')
2915 self.waitUntilSettled()
2916 self.worker.release('.*-merge')
2917 self.waitUntilSettled()
2918 self.worker.release('.*-merge')
2919 self.waitUntilSettled()
2920
2921 self.assertEqual(len(self.builds), 6)
2922 self.assertEqual(self.builds[0].name, 'project-test1')
2923 self.assertEqual(self.builds[1].name, 'project-test2')
2924 self.assertEqual(self.builds[2].name, 'project-test1')
2925 self.assertEqual(self.builds[3].name, 'project-test2')
2926 self.assertEqual(self.builds[4].name, 'project-test1')
2927 self.assertEqual(self.builds[5].name, 'project-test2')
2928
2929 self.assertTrue(self.job_has_changes(self.builds[0], B))
2930 self.assertFalse(self.job_has_changes(self.builds[0], A))
2931 self.assertFalse(self.job_has_changes(self.builds[0], C))
2932
2933 self.assertTrue(self.job_has_changes(self.builds[2], B))
2934 self.assertTrue(self.job_has_changes(self.builds[2], C))
2935 self.assertFalse(self.job_has_changes(self.builds[2], A))
2936
2937 self.assertTrue(self.job_has_changes(self.builds[4], B))
2938 self.assertTrue(self.job_has_changes(self.builds[4], C))
2939 self.assertTrue(self.job_has_changes(self.builds[4], A))
2940
2941 self.worker.release()
2942 self.waitUntilSettled()
2943
2944 self.assertEqual(A.data['status'], 'MERGED')
2945 self.assertEqual(A.reported, 2)
2946 self.assertEqual(B.data['status'], 'MERGED')
2947 self.assertEqual(B.reported, 2)
2948 self.assertEqual(C.data['status'], 'MERGED')
2949 self.assertEqual(C.reported, 2)
2950
2951 client.shutdown()
2952 self.assertEqual(r, True)
2953
2954 def test_client_promote_dependent(self):
2955 "Test that the RPC client can promote a dependent change"
2956 # C (depends on B) -> B -> A ; then promote C to get:
2957 # A -> C (depends on B) -> B
2958 self.worker.hold_jobs_in_build = True
2959 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2960 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2961 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
2962
2963 C.setDependsOn(B, 1)
2964
2965 A.addApproval('CRVW', 2)
2966 B.addApproval('CRVW', 2)
2967 C.addApproval('CRVW', 2)
2968
2969 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2970 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2971 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
2972
2973 self.waitUntilSettled()
2974
2975 client = zuul.rpcclient.RPCClient('127.0.0.1',
2976 self.gearman_server.port)
2977 r = client.promote(pipeline='gate',
2978 change_ids=['3,1'])
2979
James E. Blair78acec92014-02-06 07:11:32 -08002980 self.waitUntilSettled()
James E. Blair36658cf2013-12-06 17:53:48 -08002981 self.worker.release('.*-merge')
2982 self.waitUntilSettled()
2983 self.worker.release('.*-merge')
2984 self.waitUntilSettled()
2985 self.worker.release('.*-merge')
2986 self.waitUntilSettled()
2987
2988 self.assertEqual(len(self.builds), 6)
2989 self.assertEqual(self.builds[0].name, 'project-test1')
2990 self.assertEqual(self.builds[1].name, 'project-test2')
2991 self.assertEqual(self.builds[2].name, 'project-test1')
2992 self.assertEqual(self.builds[3].name, 'project-test2')
2993 self.assertEqual(self.builds[4].name, 'project-test1')
2994 self.assertEqual(self.builds[5].name, 'project-test2')
2995
2996 self.assertTrue(self.job_has_changes(self.builds[0], B))
2997 self.assertFalse(self.job_has_changes(self.builds[0], A))
2998 self.assertFalse(self.job_has_changes(self.builds[0], C))
2999
3000 self.assertTrue(self.job_has_changes(self.builds[2], B))
3001 self.assertTrue(self.job_has_changes(self.builds[2], C))
3002 self.assertFalse(self.job_has_changes(self.builds[2], A))
3003
3004 self.assertTrue(self.job_has_changes(self.builds[4], B))
3005 self.assertTrue(self.job_has_changes(self.builds[4], C))
3006 self.assertTrue(self.job_has_changes(self.builds[4], A))
3007
3008 self.worker.release()
3009 self.waitUntilSettled()
3010
3011 self.assertEqual(A.data['status'], 'MERGED')
3012 self.assertEqual(A.reported, 2)
3013 self.assertEqual(B.data['status'], 'MERGED')
3014 self.assertEqual(B.reported, 2)
3015 self.assertEqual(C.data['status'], 'MERGED')
3016 self.assertEqual(C.reported, 2)
3017
3018 client.shutdown()
3019 self.assertEqual(r, True)
3020
3021 def test_client_promote_negative(self):
3022 "Test that the RPC client returns errors for promotion"
3023 self.worker.hold_jobs_in_build = True
3024 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3025 A.addApproval('CRVW', 2)
3026 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3027 self.waitUntilSettled()
3028
3029 client = zuul.rpcclient.RPCClient('127.0.0.1',
3030 self.gearman_server.port)
3031
3032 with testtools.ExpectedException(zuul.rpcclient.RPCFailure):
3033 r = client.promote(pipeline='nonexistent',
3034 change_ids=['2,1', '3,1'])
3035 client.shutdown()
3036 self.assertEqual(r, False)
3037
3038 with testtools.ExpectedException(zuul.rpcclient.RPCFailure):
3039 r = client.promote(pipeline='gate',
3040 change_ids=['4,1'])
3041 client.shutdown()
3042 self.assertEqual(r, False)
3043
3044 self.worker.hold_jobs_in_build = False
3045 self.worker.release()
3046 self.waitUntilSettled()
Clark Boylan7603a372014-01-21 11:43:20 -08003047
3048 def test_queue_rate_limiting(self):
3049 "Test that DependentPipelines are rate limited with dep across window"
3050 self.config.set('zuul', 'layout_config',
3051 'tests/fixtures/layout-rate-limit.yaml')
3052 self.sched.reconfigure(self.config)
3053 self.worker.hold_jobs_in_build = True
3054 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3055 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
3056 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
3057
3058 C.setDependsOn(B, 1)
3059 self.worker.addFailTest('project-test1', A)
3060
3061 A.addApproval('CRVW', 2)
3062 B.addApproval('CRVW', 2)
3063 C.addApproval('CRVW', 2)
3064
3065 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3066 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3067 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
3068 self.waitUntilSettled()
3069
3070 # Only A and B will have their merge jobs queued because
3071 # window is 2.
3072 self.assertEqual(len(self.builds), 2)
3073 self.assertEqual(self.builds[0].name, 'project-merge')
3074 self.assertEqual(self.builds[1].name, 'project-merge')
3075
3076 self.worker.release('.*-merge')
3077 self.waitUntilSettled()
3078 self.worker.release('.*-merge')
3079 self.waitUntilSettled()
3080
3081 # Only A and B will have their test jobs queued because
3082 # window is 2.
3083 self.assertEqual(len(self.builds), 4)
3084 self.assertEqual(self.builds[0].name, 'project-test1')
3085 self.assertEqual(self.builds[1].name, 'project-test2')
3086 self.assertEqual(self.builds[2].name, 'project-test1')
3087 self.assertEqual(self.builds[3].name, 'project-test2')
3088
3089 self.worker.release('project-.*')
3090 self.waitUntilSettled()
3091
3092 queue = self.sched.layout.pipelines['gate'].queues[0]
3093 # A failed so window is reduced by 1 to 1.
3094 self.assertEqual(queue.window, 1)
3095 self.assertEqual(queue.window_floor, 1)
3096 self.assertEqual(A.data['status'], 'NEW')
3097
3098 # Gate is reset and only B's merge job is queued because
3099 # window shrunk to 1.
3100 self.assertEqual(len(self.builds), 1)
3101 self.assertEqual(self.builds[0].name, 'project-merge')
3102
3103 self.worker.release('.*-merge')
3104 self.waitUntilSettled()
3105
3106 # Only B's test jobs are queued because window is still 1.
3107 self.assertEqual(len(self.builds), 2)
3108 self.assertEqual(self.builds[0].name, 'project-test1')
3109 self.assertEqual(self.builds[1].name, 'project-test2')
3110
3111 self.worker.release('project-.*')
3112 self.waitUntilSettled()
3113
3114 # B was successfully merged so window is increased to 2.
3115 self.assertEqual(queue.window, 2)
3116 self.assertEqual(queue.window_floor, 1)
3117 self.assertEqual(B.data['status'], 'MERGED')
3118
3119 # Only C is left and its merge job is queued.
3120 self.assertEqual(len(self.builds), 1)
3121 self.assertEqual(self.builds[0].name, 'project-merge')
3122
3123 self.worker.release('.*-merge')
3124 self.waitUntilSettled()
3125
3126 # After successful merge job the test jobs for C are queued.
3127 self.assertEqual(len(self.builds), 2)
3128 self.assertEqual(self.builds[0].name, 'project-test1')
3129 self.assertEqual(self.builds[1].name, 'project-test2')
3130
3131 self.worker.release('project-.*')
3132 self.waitUntilSettled()
3133
3134 # C successfully merged so window is bumped to 3.
3135 self.assertEqual(queue.window, 3)
3136 self.assertEqual(queue.window_floor, 1)
3137 self.assertEqual(C.data['status'], 'MERGED')
3138
3139 def test_queue_rate_limiting_dependent(self):
3140 "Test that DependentPipelines are rate limited with dep in window"
3141 self.config.set('zuul', 'layout_config',
3142 'tests/fixtures/layout-rate-limit.yaml')
3143 self.sched.reconfigure(self.config)
3144 self.worker.hold_jobs_in_build = True
3145 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3146 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
3147 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
3148
3149 B.setDependsOn(A, 1)
3150
3151 self.worker.addFailTest('project-test1', A)
3152
3153 A.addApproval('CRVW', 2)
3154 B.addApproval('CRVW', 2)
3155 C.addApproval('CRVW', 2)
3156
3157 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3158 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3159 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
3160 self.waitUntilSettled()
3161
3162 # Only A and B will have their merge jobs queued because
3163 # window is 2.
3164 self.assertEqual(len(self.builds), 2)
3165 self.assertEqual(self.builds[0].name, 'project-merge')
3166 self.assertEqual(self.builds[1].name, 'project-merge')
3167
3168 self.worker.release('.*-merge')
3169 self.waitUntilSettled()
3170 self.worker.release('.*-merge')
3171 self.waitUntilSettled()
3172
3173 # Only A and B will have their test jobs queued because
3174 # window is 2.
3175 self.assertEqual(len(self.builds), 4)
3176 self.assertEqual(self.builds[0].name, 'project-test1')
3177 self.assertEqual(self.builds[1].name, 'project-test2')
3178 self.assertEqual(self.builds[2].name, 'project-test1')
3179 self.assertEqual(self.builds[3].name, 'project-test2')
3180
3181 self.worker.release('project-.*')
3182 self.waitUntilSettled()
3183
3184 queue = self.sched.layout.pipelines['gate'].queues[0]
3185 # A failed so window is reduced by 1 to 1.
3186 self.assertEqual(queue.window, 1)
3187 self.assertEqual(queue.window_floor, 1)
3188 self.assertEqual(A.data['status'], 'NEW')
3189 self.assertEqual(B.data['status'], 'NEW')
3190
3191 # Gate is reset and only C's merge job is queued because
3192 # window shrunk to 1 and A and B were dequeued.
3193 self.assertEqual(len(self.builds), 1)
3194 self.assertEqual(self.builds[0].name, 'project-merge')
3195
3196 self.worker.release('.*-merge')
3197 self.waitUntilSettled()
3198
3199 # Only C's test jobs are queued because window is still 1.
3200 self.assertEqual(len(self.builds), 2)
3201 self.assertEqual(self.builds[0].name, 'project-test1')
3202 self.assertEqual(self.builds[1].name, 'project-test2')
3203
3204 self.worker.release('project-.*')
3205 self.waitUntilSettled()
3206
3207 # C was successfully merged so window is increased to 2.
3208 self.assertEqual(queue.window, 2)
3209 self.assertEqual(queue.window_floor, 1)
3210 self.assertEqual(C.data['status'], 'MERGED')
Joshua Heskethba8776a2014-01-12 14:35:40 +08003211
3212 def test_worker_update_metadata(self):
3213 "Test if a worker can send back metadata about itself"
3214 self.worker.hold_jobs_in_build = True
3215
3216 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3217 A.addApproval('CRVW', 2)
3218 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3219 self.waitUntilSettled()
3220
3221 self.assertEqual(len(self.launcher.builds), 1)
3222
3223 self.log.debug('Current builds:')
3224 self.log.debug(self.launcher.builds)
3225
3226 start = time.time()
3227 while True:
3228 if time.time() - start > 10:
3229 raise Exception("Timeout waiting for gearman server to report "
3230 + "back to the client")
3231 build = self.launcher.builds.values()[0]
3232 if build.worker.name == "My Worker":
3233 break
3234 else:
3235 time.sleep(0)
3236
3237 self.log.debug(build)
3238 self.assertEqual("My Worker", build.worker.name)
3239 self.assertEqual("localhost", build.worker.hostname)
3240 self.assertEqual(['127.0.0.1', '192.168.1.1'], build.worker.ips)
3241 self.assertEqual("zuul.example.org", build.worker.fqdn)
3242 self.assertEqual("FakeBuilder", build.worker.program)
3243 self.assertEqual("v1.1", build.worker.version)
3244 self.assertEqual({'something': 'else'}, build.worker.extra)
3245
3246 self.worker.hold_jobs_in_build = False
3247 self.worker.release()
3248 self.waitUntilSettled()
Joshua Hesketh3979e3e2014-03-04 11:21:10 +11003249
3250 def test_footer_message(self):
3251 "Test a pipeline's footer message is correctly added to the report."
3252 self.config.set('zuul', 'layout_config',
3253 'tests/fixtures/layout-footer-message.yaml')
3254 self.sched.reconfigure(self.config)
3255 self.registerJobs()
3256
3257 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3258 A.addApproval('CRVW', 2)
3259 self.worker.addFailTest('test1', A)
3260 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3261 self.waitUntilSettled()
3262
3263 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
3264 B.addApproval('CRVW', 2)
3265 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3266 self.waitUntilSettled()
3267
3268 self.assertEqual(2, len(self.smtp_messages))
3269
3270 failure_body = """\
3271Build failed. For information on how to proceed, see \
3272http://wiki.example.org/Test_Failures
3273
3274- test1 http://logs.example.com/1/1/gate/test1/0 : FAILURE in 0s
3275- test2 http://logs.example.com/1/1/gate/test2/1 : SUCCESS in 0s
3276
3277For CI problems and help debugging, contact ci@example.org"""
3278
3279 success_body = """\
3280Build succeeded.
3281
3282- test1 http://logs.example.com/2/1/gate/test1/2 : SUCCESS in 0s
3283- test2 http://logs.example.com/2/1/gate/test2/3 : SUCCESS in 0s
3284
3285For CI problems and help debugging, contact ci@example.org"""
3286
3287 self.assertEqual(failure_body, self.smtp_messages[0]['body'])
3288 self.assertEqual(success_body, self.smtp_messages[1]['body'])
Joshua Heskethb7179772014-01-30 23:30:46 +11003289
3290 def test_merge_failure_reporters(self):
3291 """Check that the config is set up correctly"""
3292
3293 self.config.set('zuul', 'layout_config',
3294 'tests/fixtures/layout-merge-failure.yaml')
3295 self.sched.reconfigure(self.config)
3296 self.registerJobs()
3297
3298 self.assertEqual(
Jeremy Stanley1c2c3c22015-06-15 21:23:19 +00003299 "Merge Failed.\n\nThis change or one of its cross-repo "
3300 "dependencies was unable to be automatically merged with the "
3301 "current state of its repository. Please rebase the change and "
3302 "upload a new patchset.",
Joshua Heskethb7179772014-01-30 23:30:46 +11003303 self.sched.layout.pipelines['check'].merge_failure_message)
3304 self.assertEqual(
3305 "The merge failed! For more information...",
3306 self.sched.layout.pipelines['gate'].merge_failure_message)
3307
3308 self.assertEqual(
3309 len(self.sched.layout.pipelines['check'].merge_failure_actions), 1)
3310 self.assertEqual(
3311 len(self.sched.layout.pipelines['gate'].merge_failure_actions), 2)
3312
3313 self.assertTrue(isinstance(
3314 self.sched.layout.pipelines['check'].merge_failure_actions[0].
3315 reporter, zuul.reporter.gerrit.Reporter))
3316
3317 self.assertTrue(
3318 (
3319 isinstance(self.sched.layout.pipelines['gate'].
3320 merge_failure_actions[0].reporter,
3321 zuul.reporter.smtp.Reporter) and
3322 isinstance(self.sched.layout.pipelines['gate'].
3323 merge_failure_actions[1].reporter,
3324 zuul.reporter.gerrit.Reporter)
3325 ) or (
3326 isinstance(self.sched.layout.pipelines['gate'].
3327 merge_failure_actions[0].reporter,
3328 zuul.reporter.gerrit.Reporter) and
3329 isinstance(self.sched.layout.pipelines['gate'].
3330 merge_failure_actions[1].reporter,
3331 zuul.reporter.smtp.Reporter)
3332 )
3333 )
3334
3335 def test_merge_failure_reports(self):
3336 """Check that when a change fails to merge the correct message is sent
3337 to the correct reporter"""
3338 self.config.set('zuul', 'layout_config',
3339 'tests/fixtures/layout-merge-failure.yaml')
3340 self.sched.reconfigure(self.config)
3341 self.registerJobs()
3342
3343 # Check a test failure isn't reported to SMTP
3344 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3345 A.addApproval('CRVW', 2)
3346 self.worker.addFailTest('project-test1', A)
3347 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3348 self.waitUntilSettled()
3349
3350 self.assertEqual(3, len(self.history)) # 3 jobs
3351 self.assertEqual(0, len(self.smtp_messages))
3352
3353 # Check a merge failure is reported to SMTP
3354 # B should be merged, but C will conflict with B
3355 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
3356 B.addPatchset(['conflict'])
3357 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
3358 C.addPatchset(['conflict'])
3359 B.addApproval('CRVW', 2)
3360 C.addApproval('CRVW', 2)
3361 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3362 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
3363 self.waitUntilSettled()
3364
3365 self.assertEqual(6, len(self.history)) # A and B jobs
3366 self.assertEqual(1, len(self.smtp_messages))
3367 self.assertEqual('The merge failed! For more information...',
3368 self.smtp_messages[0]['body'])
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11003369
3370 def test_swift_instructions(self):
3371 "Test that the correct swift instructions are sent to the workers"
3372 self.config.set('zuul', 'layout_config',
3373 'tests/fixtures/layout-swift.yaml')
3374 self.sched.reconfigure(self.config)
3375 self.registerJobs()
3376
3377 self.worker.hold_jobs_in_build = True
3378 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3379
3380 A.addApproval('CRVW', 2)
3381 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3382 self.waitUntilSettled()
3383
3384 self.assertEqual(
3385 "https://storage.example.org/V1/AUTH_account/merge_logs/1/1/1/"
3386 "gate/test-merge/",
Joshua Hesketh76dee532014-07-03 15:39:13 +10003387 self.builds[0].parameters['SWIFT_logs_URL'][:-7])
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11003388 self.assertEqual(5,
3389 len(self.builds[0].parameters['SWIFT_logs_HMAC_BODY'].
3390 split('\n')))
3391 self.assertIn('SWIFT_logs_SIGNATURE', self.builds[0].parameters)
3392
3393 self.assertEqual(
3394 "https://storage.example.org/V1/AUTH_account/logs/1/1/1/"
3395 "gate/test-test/",
Joshua Hesketh76dee532014-07-03 15:39:13 +10003396 self.builds[1].parameters['SWIFT_logs_URL'][:-7])
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11003397 self.assertEqual(5,
3398 len(self.builds[1].parameters['SWIFT_logs_HMAC_BODY'].
3399 split('\n')))
3400 self.assertIn('SWIFT_logs_SIGNATURE', self.builds[1].parameters)
3401
3402 self.assertEqual(
3403 "https://storage.example.org/V1/AUTH_account/stash/1/1/1/"
3404 "gate/test-test/",
Joshua Hesketh76dee532014-07-03 15:39:13 +10003405 self.builds[1].parameters['SWIFT_MOSTLY_URL'][:-7])
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11003406 self.assertEqual(5,
3407 len(self.builds[1].
3408 parameters['SWIFT_MOSTLY_HMAC_BODY'].split('\n')))
3409 self.assertIn('SWIFT_MOSTLY_SIGNATURE', self.builds[1].parameters)
3410
3411 self.worker.hold_jobs_in_build = False
3412 self.worker.release()
3413 self.waitUntilSettled()
Joshua Hesketh85af4e92014-02-21 08:28:58 -08003414
3415 def test_client_get_running_jobs(self):
3416 "Test that the RPC client can get a list of running jobs"
3417 self.worker.hold_jobs_in_build = True
3418 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3419 A.addApproval('CRVW', 2)
3420 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3421 self.waitUntilSettled()
3422
3423 client = zuul.rpcclient.RPCClient('127.0.0.1',
3424 self.gearman_server.port)
3425
3426 # Wait for gearman server to send the initial workData back to zuul
3427 start = time.time()
3428 while True:
3429 if time.time() - start > 10:
3430 raise Exception("Timeout waiting for gearman server to report "
3431 + "back to the client")
3432 build = self.launcher.builds.values()[0]
3433 if build.worker.name == "My Worker":
3434 break
3435 else:
3436 time.sleep(0)
3437
3438 running_items = client.get_running_jobs()
3439
3440 self.assertEqual(1, len(running_items))
3441 running_item = running_items[0]
3442 self.assertEqual([], running_item['failing_reasons'])
3443 self.assertEqual([], running_item['items_behind'])
3444 self.assertEqual('https://hostname/1', running_item['url'])
3445 self.assertEqual(None, running_item['item_ahead'])
3446 self.assertEqual('org/project', running_item['project'])
3447 self.assertEqual(None, running_item['remaining_time'])
3448 self.assertEqual(True, running_item['active'])
3449 self.assertEqual('1,1', running_item['id'])
3450
3451 self.assertEqual(3, len(running_item['jobs']))
3452 for job in running_item['jobs']:
3453 if job['name'] == 'project-merge':
3454 self.assertEqual('project-merge', job['name'])
3455 self.assertEqual('gate', job['pipeline'])
3456 self.assertEqual(False, job['retry'])
Joshua Hesketh85af4e92014-02-21 08:28:58 -08003457 self.assertEqual('https://server/job/project-merge/0/',
3458 job['url'])
3459 self.assertEqual(7, len(job['worker']))
3460 self.assertEqual(False, job['canceled'])
3461 self.assertEqual(True, job['voting'])
3462 self.assertEqual(None, job['result'])
3463 self.assertEqual('gate', job['pipeline'])
3464 break
3465
3466 self.worker.hold_jobs_in_build = False
3467 self.worker.release()
3468 self.waitUntilSettled()
3469
3470 running_items = client.get_running_jobs()
3471 self.assertEqual(0, len(running_items))
James E. Blairbadc1ad2014-04-28 13:55:14 -07003472
3473 def test_nonvoting_pipeline(self):
3474 "Test that a nonvoting pipeline (experimental) can still report"
3475
Joshua Heskethcc017ea2014-04-30 19:55:25 +10003476 A = self.fake_gerrit.addFakeChange('org/experimental-project',
3477 'master', 'A')
James E. Blairbadc1ad2014-04-28 13:55:14 -07003478 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3479 self.waitUntilSettled()
Joshua Heskethcc017ea2014-04-30 19:55:25 +10003480 self.assertEqual(
3481 self.getJobFromHistory('experimental-project-test').result,
3482 'SUCCESS')
James E. Blairbadc1ad2014-04-28 13:55:14 -07003483 self.assertEqual(A.reported, 1)
James E. Blair5ee24252014-12-30 10:12:29 -08003484
3485 def test_crd_gate(self):
3486 "Test cross-repo dependencies"
3487 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3488 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3489 A.addApproval('CRVW', 2)
3490 B.addApproval('CRVW', 2)
3491
3492 AM2 = self.fake_gerrit.addFakeChange('org/project1', 'master', 'AM2')
3493 AM1 = self.fake_gerrit.addFakeChange('org/project1', 'master', 'AM1')
3494 AM2.setMerged()
3495 AM1.setMerged()
3496
3497 BM2 = self.fake_gerrit.addFakeChange('org/project2', 'master', 'BM2')
3498 BM1 = self.fake_gerrit.addFakeChange('org/project2', 'master', 'BM1')
3499 BM2.setMerged()
3500 BM1.setMerged()
3501
3502 # A -> AM1 -> AM2
3503 # B -> BM1 -> BM2
3504 # A Depends-On: B
3505 # M2 is here to make sure it is never queried. If it is, it
3506 # means zuul is walking down the entire history of merged
3507 # changes.
3508
3509 B.setDependsOn(BM1, 1)
3510 BM1.setDependsOn(BM2, 1)
3511
3512 A.setDependsOn(AM1, 1)
3513 AM1.setDependsOn(AM2, 1)
3514
3515 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3516 A.subject, B.data['id'])
3517
3518 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3519 self.waitUntilSettled()
3520
3521 self.assertEqual(A.data['status'], 'NEW')
3522 self.assertEqual(B.data['status'], 'NEW')
3523
3524 source = self.sched.layout.pipelines['gate'].source
3525 source.maintainCache([])
3526
3527 self.worker.hold_jobs_in_build = True
3528 B.addApproval('APRV', 1)
3529 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3530 self.waitUntilSettled()
3531
3532 self.worker.release('.*-merge')
3533 self.waitUntilSettled()
3534 self.worker.release('.*-merge')
3535 self.waitUntilSettled()
3536 self.worker.hold_jobs_in_build = False
3537 self.worker.release()
3538 self.waitUntilSettled()
3539
3540 self.assertEqual(AM2.queried, 0)
3541 self.assertEqual(BM2.queried, 0)
3542 self.assertEqual(A.data['status'], 'MERGED')
3543 self.assertEqual(B.data['status'], 'MERGED')
3544 self.assertEqual(A.reported, 2)
3545 self.assertEqual(B.reported, 2)
3546
James E. Blair8f78d882015-02-05 08:51:37 -08003547 self.assertEqual(self.getJobFromHistory('project1-merge').changes,
3548 '2,1 1,1')
3549
3550 def test_crd_branch(self):
3551 "Test cross-repo dependencies in multiple branches"
3552 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3553 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3554 C = self.fake_gerrit.addFakeChange('org/project2', 'mp', 'C')
3555 C.data['id'] = B.data['id']
3556 A.addApproval('CRVW', 2)
3557 B.addApproval('CRVW', 2)
3558 C.addApproval('CRVW', 2)
3559
3560 # A Depends-On: B+C
3561 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3562 A.subject, B.data['id'])
3563
3564 self.worker.hold_jobs_in_build = True
3565 B.addApproval('APRV', 1)
3566 C.addApproval('APRV', 1)
3567 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3568 self.waitUntilSettled()
3569
3570 self.worker.release('.*-merge')
3571 self.waitUntilSettled()
3572 self.worker.release('.*-merge')
3573 self.waitUntilSettled()
3574 self.worker.release('.*-merge')
3575 self.waitUntilSettled()
3576 self.worker.hold_jobs_in_build = False
3577 self.worker.release()
3578 self.waitUntilSettled()
3579
3580 self.assertEqual(A.data['status'], 'MERGED')
3581 self.assertEqual(B.data['status'], 'MERGED')
3582 self.assertEqual(C.data['status'], 'MERGED')
3583 self.assertEqual(A.reported, 2)
3584 self.assertEqual(B.reported, 2)
3585 self.assertEqual(C.reported, 2)
3586
3587 self.assertEqual(self.getJobFromHistory('project1-merge').changes,
3588 '2,1 3,1 1,1')
3589
3590 def test_crd_multiline(self):
3591 "Test multiple depends-on lines in commit"
3592 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3593 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3594 C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
3595 A.addApproval('CRVW', 2)
3596 B.addApproval('CRVW', 2)
3597 C.addApproval('CRVW', 2)
3598
3599 # A Depends-On: B+C
3600 A.data['commitMessage'] = '%s\n\nDepends-On: %s\nDepends-On: %s\n' % (
3601 A.subject, B.data['id'], C.data['id'])
3602
3603 self.worker.hold_jobs_in_build = True
3604 B.addApproval('APRV', 1)
3605 C.addApproval('APRV', 1)
3606 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3607 self.waitUntilSettled()
3608
3609 self.worker.release('.*-merge')
3610 self.waitUntilSettled()
3611 self.worker.release('.*-merge')
3612 self.waitUntilSettled()
3613 self.worker.release('.*-merge')
3614 self.waitUntilSettled()
3615 self.worker.hold_jobs_in_build = False
3616 self.worker.release()
3617 self.waitUntilSettled()
3618
3619 self.assertEqual(A.data['status'], 'MERGED')
3620 self.assertEqual(B.data['status'], 'MERGED')
3621 self.assertEqual(C.data['status'], 'MERGED')
3622 self.assertEqual(A.reported, 2)
3623 self.assertEqual(B.reported, 2)
3624 self.assertEqual(C.reported, 2)
3625
3626 self.assertEqual(self.getJobFromHistory('project1-merge').changes,
3627 '2,1 3,1 1,1')
James E. Blair5ee24252014-12-30 10:12:29 -08003628
3629 def test_crd_unshared_gate(self):
3630 "Test cross-repo dependencies in unshared gate queues"
3631 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3632 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
3633 A.addApproval('CRVW', 2)
3634 B.addApproval('CRVW', 2)
3635
3636 # A Depends-On: B
3637 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3638 A.subject, B.data['id'])
3639
3640 # A and B do not share a queue, make sure that A is unable to
3641 # enqueue B (and therefore, A is unable to be enqueued).
3642 B.addApproval('APRV', 1)
3643 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3644 self.waitUntilSettled()
3645
3646 self.assertEqual(A.data['status'], 'NEW')
3647 self.assertEqual(B.data['status'], 'NEW')
3648 self.assertEqual(A.reported, 0)
3649 self.assertEqual(B.reported, 0)
3650 self.assertEqual(len(self.history), 0)
3651
3652 # Enqueue and merge B alone.
3653 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3654 self.waitUntilSettled()
3655
3656 self.assertEqual(B.data['status'], 'MERGED')
3657 self.assertEqual(B.reported, 2)
3658
3659 # Now that B is merged, A should be able to be enqueued and
3660 # merged.
3661 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3662 self.waitUntilSettled()
3663
3664 self.assertEqual(A.data['status'], 'MERGED')
3665 self.assertEqual(A.reported, 2)
3666
James E. Blair96698e22015-04-02 07:48:21 -07003667 def test_crd_gate_reverse(self):
3668 "Test reverse cross-repo dependencies"
3669 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3670 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3671 A.addApproval('CRVW', 2)
3672 B.addApproval('CRVW', 2)
3673
3674 # A Depends-On: B
3675
3676 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3677 A.subject, B.data['id'])
3678
3679 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3680 self.waitUntilSettled()
3681
3682 self.assertEqual(A.data['status'], 'NEW')
3683 self.assertEqual(B.data['status'], 'NEW')
3684
3685 self.worker.hold_jobs_in_build = True
3686 A.addApproval('APRV', 1)
3687 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3688 self.waitUntilSettled()
3689
3690 self.worker.release('.*-merge')
3691 self.waitUntilSettled()
3692 self.worker.release('.*-merge')
3693 self.waitUntilSettled()
3694 self.worker.hold_jobs_in_build = False
3695 self.worker.release()
3696 self.waitUntilSettled()
3697
3698 self.assertEqual(A.data['status'], 'MERGED')
3699 self.assertEqual(B.data['status'], 'MERGED')
3700 self.assertEqual(A.reported, 2)
3701 self.assertEqual(B.reported, 2)
3702
3703 self.assertEqual(self.getJobFromHistory('project1-merge').changes,
3704 '2,1 1,1')
3705
James E. Blair5ee24252014-12-30 10:12:29 -08003706 def test_crd_cycle(self):
3707 "Test cross-repo dependency cycles"
3708 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3709 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3710 A.addApproval('CRVW', 2)
3711 B.addApproval('CRVW', 2)
3712
3713 # A -> B -> A (via commit-depends)
3714
3715 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3716 A.subject, B.data['id'])
3717 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3718 B.subject, A.data['id'])
3719
3720 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3721 self.waitUntilSettled()
3722
3723 self.assertEqual(A.reported, 0)
3724 self.assertEqual(B.reported, 0)
3725 self.assertEqual(A.data['status'], 'NEW')
3726 self.assertEqual(B.data['status'], 'NEW')
James E. Blairbfb8e042014-12-30 17:01:44 -08003727
Evgeny Antyshev0deaaad2015-08-03 20:22:56 +00003728 def test_crd_gate_unknown(self):
3729 "Test unknown projects in dependent pipeline"
3730 self.init_repo("org/unknown")
3731 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3732 B = self.fake_gerrit.addFakeChange('org/unknown', 'master', 'B')
3733 A.addApproval('CRVW', 2)
3734 B.addApproval('CRVW', 2)
3735
3736 # A Depends-On: B
3737 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3738 A.subject, B.data['id'])
3739
3740 B.addApproval('APRV', 1)
3741 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3742 self.waitUntilSettled()
3743
3744 # Unknown projects cannot share a queue with any other
3745 # since they don't have common jobs with any other (they have no jobs).
3746 # Changes which depend on unknown project changes
3747 # should not be processed in dependent pipeline
3748 self.assertEqual(A.data['status'], 'NEW')
3749 self.assertEqual(B.data['status'], 'NEW')
3750 self.assertEqual(A.reported, 0)
3751 self.assertEqual(B.reported, 0)
3752 self.assertEqual(len(self.history), 0)
3753
3754 # Simulate change B being gated outside this layout
3755 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3756 B.setMerged()
3757 self.waitUntilSettled()
3758 self.assertEqual(len(self.history), 0)
3759
3760 # Now that B is merged, A should be able to be enqueued and
3761 # merged.
3762 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3763 self.waitUntilSettled()
3764
3765 self.assertEqual(A.data['status'], 'MERGED')
3766 self.assertEqual(A.reported, 2)
3767 self.assertEqual(B.data['status'], 'MERGED')
3768 self.assertEqual(B.reported, 0)
3769
James E. Blairbfb8e042014-12-30 17:01:44 -08003770 def test_crd_check(self):
3771 "Test cross-repo dependencies in independent pipelines"
3772
3773 self.gearman_server.hold_jobs_in_queue = True
3774 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3775 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3776
3777 # A Depends-On: B
3778 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3779 A.subject, B.data['id'])
3780
3781 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3782 self.waitUntilSettled()
3783
3784 queue = self.gearman_server.getQueue()
3785 ref = self.getParameter(queue[-1], 'ZUUL_REF')
3786 self.gearman_server.hold_jobs_in_queue = False
3787 self.gearman_server.release()
3788 self.waitUntilSettled()
3789
3790 path = os.path.join(self.git_root, "org/project1")
3791 repo = git.Repo(path)
3792 repo_messages = [c.message.strip() for c in repo.iter_commits(ref)]
3793 repo_messages.reverse()
3794 correct_messages = ['initial commit', 'A-1']
3795 self.assertEqual(repo_messages, correct_messages)
3796
3797 path = os.path.join(self.git_root, "org/project2")
3798 repo = git.Repo(path)
3799 repo_messages = [c.message.strip() for c in repo.iter_commits(ref)]
3800 repo_messages.reverse()
3801 correct_messages = ['initial commit', 'B-1']
3802 self.assertEqual(repo_messages, correct_messages)
3803
3804 self.assertEqual(A.data['status'], 'NEW')
3805 self.assertEqual(B.data['status'], 'NEW')
3806 self.assertEqual(A.reported, 1)
3807 self.assertEqual(B.reported, 0)
3808
3809 self.assertEqual(self.history[0].changes, '2,1 1,1')
3810 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 0)
James E. Blair8f78d882015-02-05 08:51:37 -08003811
James E. Blairdbfe1cd2015-02-07 11:41:19 -08003812 def test_crd_check_git_depends(self):
3813 "Test single-repo dependencies in independent pipelines"
James E. Blairb8c16472015-05-05 14:55:26 -07003814 self.gearman_server.hold_jobs_in_build = True
James E. Blairdbfe1cd2015-02-07 11:41:19 -08003815 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3816 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
3817
3818 # Add two git-dependent changes and make sure they both report
3819 # success.
3820 B.setDependsOn(A, 1)
3821 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3822 self.waitUntilSettled()
3823 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
3824 self.waitUntilSettled()
3825
James E. Blairb8c16472015-05-05 14:55:26 -07003826 self.orderedRelease()
3827 self.gearman_server.hold_jobs_in_build = False
James E. Blairdbfe1cd2015-02-07 11:41:19 -08003828 self.waitUntilSettled()
3829
3830 self.assertEqual(A.data['status'], 'NEW')
3831 self.assertEqual(B.data['status'], 'NEW')
3832 self.assertEqual(A.reported, 1)
3833 self.assertEqual(B.reported, 1)
3834
3835 self.assertEqual(self.history[0].changes, '1,1')
3836 self.assertEqual(self.history[-1].changes, '1,1 2,1')
3837 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 0)
3838
3839 self.assertIn('Build succeeded', A.messages[0])
3840 self.assertIn('Build succeeded', B.messages[0])
3841
3842 def test_crd_check_duplicate(self):
3843 "Test duplicate check in independent pipelines"
James E. Blair1e263032015-05-07 14:35:34 -07003844 self.worker.hold_jobs_in_build = True
James E. Blairdbfe1cd2015-02-07 11:41:19 -08003845 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3846 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
3847 check_pipeline = self.sched.layout.pipelines['check']
3848
3849 # Add two git-dependent changes...
3850 B.setDependsOn(A, 1)
3851 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
3852 self.waitUntilSettled()
3853 self.assertEqual(len(check_pipeline.getAllItems()), 2)
3854
3855 # ...make sure the live one is not duplicated...
3856 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
3857 self.waitUntilSettled()
3858 self.assertEqual(len(check_pipeline.getAllItems()), 2)
3859
3860 # ...but the non-live one is able to be.
3861 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3862 self.waitUntilSettled()
3863 self.assertEqual(len(check_pipeline.getAllItems()), 3)
3864
Clark Boylandd849822015-03-02 12:38:14 -08003865 # Release jobs in order to avoid races with change A jobs
3866 # finishing before change B jobs.
James E. Blaird7650852015-05-07 15:47:37 -07003867 self.orderedRelease()
James E. Blair1e263032015-05-07 14:35:34 -07003868 self.worker.hold_jobs_in_build = False
3869 self.worker.release()
James E. Blairdbfe1cd2015-02-07 11:41:19 -08003870 self.waitUntilSettled()
3871
3872 self.assertEqual(A.data['status'], 'NEW')
3873 self.assertEqual(B.data['status'], 'NEW')
3874 self.assertEqual(A.reported, 1)
3875 self.assertEqual(B.reported, 1)
3876
3877 self.assertEqual(self.history[0].changes, '1,1 2,1')
3878 self.assertEqual(self.history[1].changes, '1,1')
3879 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 0)
3880
3881 self.assertIn('Build succeeded', A.messages[0])
3882 self.assertIn('Build succeeded', B.messages[0])
3883
Evgeny Antyshev0deaaad2015-08-03 20:22:56 +00003884 def _test_crd_check_reconfiguration(self, project1, project2):
James E. Blair8f78d882015-02-05 08:51:37 -08003885 "Test cross-repo dependencies re-enqueued in independent pipelines"
3886
3887 self.gearman_server.hold_jobs_in_queue = True
Evgeny Antyshev0deaaad2015-08-03 20:22:56 +00003888 A = self.fake_gerrit.addFakeChange(project1, 'master', 'A')
3889 B = self.fake_gerrit.addFakeChange(project2, 'master', 'B')
James E. Blair8f78d882015-02-05 08:51:37 -08003890
3891 # A Depends-On: B
3892 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3893 A.subject, B.data['id'])
3894
3895 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3896 self.waitUntilSettled()
3897
3898 self.sched.reconfigure(self.config)
3899
3900 # Make sure the items still share a change queue, and the
3901 # first one is not live.
3902 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 1)
3903 queue = self.sched.layout.pipelines['check'].queues[0]
3904 first_item = queue.queue[0]
3905 for item in queue.queue:
3906 self.assertEqual(item.queue, first_item.queue)
3907 self.assertFalse(first_item.live)
3908 self.assertTrue(queue.queue[1].live)
3909
3910 self.gearman_server.hold_jobs_in_queue = False
3911 self.gearman_server.release()
3912 self.waitUntilSettled()
3913
3914 self.assertEqual(A.data['status'], 'NEW')
3915 self.assertEqual(B.data['status'], 'NEW')
3916 self.assertEqual(A.reported, 1)
3917 self.assertEqual(B.reported, 0)
3918
3919 self.assertEqual(self.history[0].changes, '2,1 1,1')
3920 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 0)
James E. Blair17dd6772015-02-09 14:45:18 -08003921
Evgeny Antyshev0deaaad2015-08-03 20:22:56 +00003922 def test_crd_check_reconfiguration(self):
3923 self._test_crd_check_reconfiguration('org/project1', 'org/project2')
3924
3925 def test_crd_undefined_project(self):
3926 """Test that undefined projects in dependencies are handled for
3927 independent pipelines"""
3928 # It's a hack for fake gerrit,
3929 # as it implies repo creation upon the creation of any change
3930 self.init_repo("org/unknown")
3931 self._test_crd_check_reconfiguration('org/project1', 'org/unknown')
3932
James E. Blair17dd6772015-02-09 14:45:18 -08003933 def test_crd_check_ignore_dependencies(self):
3934 "Test cross-repo dependencies can be ignored"
3935 self.config.set('zuul', 'layout_config',
3936 'tests/fixtures/layout-ignore-dependencies.yaml')
3937 self.sched.reconfigure(self.config)
3938 self.registerJobs()
3939
3940 self.gearman_server.hold_jobs_in_queue = True
3941 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3942 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3943 C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
3944
3945 # A Depends-On: B
3946 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3947 A.subject, B.data['id'])
3948 # C git-depends on B
3949 C.setDependsOn(B, 1)
3950 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3951 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
3952 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
3953 self.waitUntilSettled()
3954
3955 # Make sure none of the items share a change queue, and all
3956 # are live.
3957 check_pipeline = self.sched.layout.pipelines['check']
3958 self.assertEqual(len(check_pipeline.queues), 3)
3959 self.assertEqual(len(check_pipeline.getAllItems()), 3)
3960 for item in check_pipeline.getAllItems():
3961 self.assertTrue(item.live)
3962
3963 self.gearman_server.hold_jobs_in_queue = False
3964 self.gearman_server.release()
3965 self.waitUntilSettled()
3966
3967 self.assertEqual(A.data['status'], 'NEW')
3968 self.assertEqual(B.data['status'], 'NEW')
3969 self.assertEqual(C.data['status'], 'NEW')
3970 self.assertEqual(A.reported, 1)
3971 self.assertEqual(B.reported, 1)
3972 self.assertEqual(C.reported, 1)
3973
3974 # Each job should have tested exactly one change
3975 for job in self.history:
3976 self.assertEqual(len(job.changes.split()), 1)
James E. Blair96698e22015-04-02 07:48:21 -07003977
3978 def test_crd_check_transitive(self):
3979 "Test transitive cross-repo dependencies"
3980 # Specifically, if A -> B -> C, and C gets a new patchset and
3981 # A gets a new patchset, ensure the test of A,2 includes B,1
3982 # and C,2 (not C,1 which would indicate stale data in the
3983 # cache for B).
3984 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3985 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3986 C = self.fake_gerrit.addFakeChange('org/project3', 'master', 'C')
3987
3988 # A Depends-On: B
3989 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3990 A.subject, B.data['id'])
3991
3992 # B Depends-On: C
3993 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3994 B.subject, C.data['id'])
3995
3996 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3997 self.waitUntilSettled()
3998 self.assertEqual(self.history[-1].changes, '3,1 2,1 1,1')
3999
4000 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
4001 self.waitUntilSettled()
4002 self.assertEqual(self.history[-1].changes, '3,1 2,1')
4003
4004 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
4005 self.waitUntilSettled()
4006 self.assertEqual(self.history[-1].changes, '3,1')
4007
4008 C.addPatchset()
4009 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(2))
4010 self.waitUntilSettled()
4011 self.assertEqual(self.history[-1].changes, '3,2')
4012
4013 A.addPatchset()
4014 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
4015 self.waitUntilSettled()
4016 self.assertEqual(self.history[-1].changes, '3,2 2,1 1,2')