blob: ead8c6ef5abe09e9e4e296fbf86ab04f339f2db7 [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]
Joshua Hesketh352264b2015-08-11 23:42:08 +100064 sched = zuul.scheduler.Scheduler({})
Maru Newby3fe5f852015-01-13 04:22:14 +000065 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
Joshua Hesketh850ccb62014-11-27 11:31:02 +1100732 def test_source_cache(self):
733 "Test that the source cache operates correctly"
James E. Blair0e933c52013-07-11 10:18:52 -0700734 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
Joshua Hesketh352264b2015-08-11 23:42:08 +1000765 self.log.debug("len %s" % self.fake_gerrit._change_cache.keys())
James E. Blair0e933c52013-07-11 10:18:52 -0700766 # there should still be changes in the cache
Joshua Hesketh352264b2015-08-11 23:42:08 +1000767 self.assertNotEqual(len(self.fake_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
K Jonathan Harkerf95e7232015-04-29 13:33:16 -0700897 def test_post_ignore_deletes(self):
898 "Test that deleting refs does not trigger post jobs"
899
900 e = {
901 "type": "ref-updated",
902 "submitter": {
903 "name": "User Name",
904 },
905 "refUpdate": {
906 "oldRev": "90f173846e3af9154517b88543ffbd1691f31366",
907 "newRev": "0000000000000000000000000000000000000000",
908 "refName": "master",
909 "project": "org/project",
910 }
911 }
912 self.fake_gerrit.addEvent(e)
913 self.waitUntilSettled()
914
915 job_names = [x.name for x in self.history]
916 self.assertEqual(len(self.history), 0)
917 self.assertNotIn('project-post', job_names)
918
919 def test_post_ignore_deletes_negative(self):
920 "Test that deleting refs does trigger post jobs"
921
922 self.config.set('zuul', 'layout_config',
923 'tests/fixtures/layout-dont-ignore-deletes.yaml')
924 self.sched.reconfigure(self.config)
925
926 e = {
927 "type": "ref-updated",
928 "submitter": {
929 "name": "User Name",
930 },
931 "refUpdate": {
932 "oldRev": "90f173846e3af9154517b88543ffbd1691f31366",
933 "newRev": "0000000000000000000000000000000000000000",
934 "refName": "master",
935 "project": "org/project",
936 }
937 }
938 self.fake_gerrit.addEvent(e)
939 self.waitUntilSettled()
940
941 job_names = [x.name for x in self.history]
942 self.assertEqual(len(self.history), 1)
943 self.assertIn('project-post', job_names)
944
James E. Blairc6294a52012-08-17 10:19:48 -0700945 def test_build_configuration_branch(self):
946 "Test that the right commits are on alternate branches"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700947
948 self.gearman_server.hold_jobs_in_queue = True
James E. Blairc6294a52012-08-17 10:19:48 -0700949 A = self.fake_gerrit.addFakeChange('org/project', 'mp', 'A')
950 B = self.fake_gerrit.addFakeChange('org/project', 'mp', 'B')
951 C = self.fake_gerrit.addFakeChange('org/project', 'mp', 'C')
952 A.addApproval('CRVW', 2)
953 B.addApproval('CRVW', 2)
954 C.addApproval('CRVW', 2)
955 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
956 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
957 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
958 self.waitUntilSettled()
959
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700960 self.gearman_server.release('.*-merge')
James E. Blairc6294a52012-08-17 10:19:48 -0700961 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700962 self.gearman_server.release('.*-merge')
James E. Blairc6294a52012-08-17 10:19:48 -0700963 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700964 self.gearman_server.release('.*-merge')
James E. Blairc6294a52012-08-17 10:19:48 -0700965 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -0700966 queue = self.gearman_server.getQueue()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700967 ref = self.getParameter(queue[-1], 'ZUUL_REF')
968 self.gearman_server.hold_jobs_in_queue = False
969 self.gearman_server.release()
James E. Blairc6294a52012-08-17 10:19:48 -0700970 self.waitUntilSettled()
971
Monty Taylorbc758832013-06-17 17:22:42 -0400972 path = os.path.join(self.git_root, "org/project")
James E. Blairc6294a52012-08-17 10:19:48 -0700973 repo = git.Repo(path)
974 repo_messages = [c.message.strip() for c in repo.iter_commits(ref)]
975 repo_messages.reverse()
James E. Blairc6294a52012-08-17 10:19:48 -0700976 correct_messages = ['initial commit', 'mp commit', 'A-1', 'B-1', 'C-1']
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400977 self.assertEqual(repo_messages, correct_messages)
James E. Blairc6294a52012-08-17 10:19:48 -0700978
979 def test_build_configuration_branch_interaction(self):
980 "Test that switching between branches works"
981 self.test_build_configuration()
982 self.test_build_configuration_branch()
983 # C has been merged, undo that
Monty Taylorbc758832013-06-17 17:22:42 -0400984 path = os.path.join(self.upstream_root, "org/project")
James E. Blairc6294a52012-08-17 10:19:48 -0700985 repo = git.Repo(path)
986 repo.heads.master.commit = repo.commit('init')
987 self.test_build_configuration()
988
989 def test_build_configuration_multi_branch(self):
990 "Test that dependent changes on multiple branches are merged"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700991
992 self.gearman_server.hold_jobs_in_queue = True
James E. Blairc6294a52012-08-17 10:19:48 -0700993 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
994 B = self.fake_gerrit.addFakeChange('org/project', 'mp', 'B')
995 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
996 A.addApproval('CRVW', 2)
997 B.addApproval('CRVW', 2)
998 C.addApproval('CRVW', 2)
999 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1000 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1001 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1002 self.waitUntilSettled()
James E. Blairbb1fe502014-03-04 10:15:06 -08001003 queue = self.gearman_server.getQueue()
1004 job_A = None
1005 for job in queue:
1006 if 'project-merge' in job.name:
1007 job_A = job
1008 ref_A = self.getParameter(job_A, 'ZUUL_REF')
1009 commit_A = self.getParameter(job_A, 'ZUUL_COMMIT')
1010 self.log.debug("Got Zuul ref for change A: %s" % ref_A)
1011 self.log.debug("Got Zuul commit for change A: %s" % commit_A)
James E. Blairc6294a52012-08-17 10:19:48 -07001012
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001013 self.gearman_server.release('.*-merge')
James E. Blairc6294a52012-08-17 10:19:48 -07001014 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -07001015 queue = self.gearman_server.getQueue()
James E. Blaird320d7e2013-07-30 16:36:20 -07001016 job_B = None
1017 for job in queue:
1018 if 'project-merge' in job.name:
1019 job_B = job
1020 ref_B = self.getParameter(job_B, 'ZUUL_REF')
James E. Blairbb1fe502014-03-04 10:15:06 -08001021 commit_B = self.getParameter(job_B, 'ZUUL_COMMIT')
James E. Blairf750aa02013-07-15 14:11:24 -07001022 self.log.debug("Got Zuul ref for change B: %s" % ref_B)
James E. Blairbb1fe502014-03-04 10:15:06 -08001023 self.log.debug("Got Zuul commit for change B: %s" % commit_B)
1024
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001025 self.gearman_server.release('.*-merge')
James E. Blairc6294a52012-08-17 10:19:48 -07001026 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -07001027 queue = self.gearman_server.getQueue()
James E. Blaird320d7e2013-07-30 16:36:20 -07001028 for job in queue:
1029 if 'project-merge' in job.name:
1030 job_C = job
1031 ref_C = self.getParameter(job_C, 'ZUUL_REF')
James E. Blairbb1fe502014-03-04 10:15:06 -08001032 commit_C = self.getParameter(job_C, 'ZUUL_COMMIT')
James E. Blairf750aa02013-07-15 14:11:24 -07001033 self.log.debug("Got Zuul ref for change C: %s" % ref_C)
James E. Blairbb1fe502014-03-04 10:15:06 -08001034 self.log.debug("Got Zuul commit for change C: %s" % commit_C)
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001035 self.gearman_server.hold_jobs_in_queue = False
1036 self.gearman_server.release()
James E. Blairc6294a52012-08-17 10:19:48 -07001037 self.waitUntilSettled()
1038
Monty Taylorbc758832013-06-17 17:22:42 -04001039 path = os.path.join(self.git_root, "org/project")
James E. Blairc6294a52012-08-17 10:19:48 -07001040 repo = git.Repo(path)
1041
1042 repo_messages = [c.message.strip()
James E. Blairf750aa02013-07-15 14:11:24 -07001043 for c in repo.iter_commits(ref_C)]
James E. Blairbb1fe502014-03-04 10:15:06 -08001044 repo_shas = [c.hexsha for c in repo.iter_commits(ref_C)]
James E. Blairc6294a52012-08-17 10:19:48 -07001045 repo_messages.reverse()
James E. Blairc6294a52012-08-17 10:19:48 -07001046 correct_messages = ['initial commit', 'A-1', 'C-1']
James E. Blairbb1fe502014-03-04 10:15:06 -08001047 # Ensure the right commits are in the history for this ref
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001048 self.assertEqual(repo_messages, correct_messages)
James E. Blairbb1fe502014-03-04 10:15:06 -08001049 # Ensure ZUUL_REF -> ZUUL_COMMIT
1050 self.assertEqual(repo_shas[0], commit_C)
James E. Blairc6294a52012-08-17 10:19:48 -07001051
1052 repo_messages = [c.message.strip()
James E. Blairf750aa02013-07-15 14:11:24 -07001053 for c in repo.iter_commits(ref_B)]
James E. Blairbb1fe502014-03-04 10:15:06 -08001054 repo_shas = [c.hexsha for c in repo.iter_commits(ref_B)]
James E. Blairc6294a52012-08-17 10:19:48 -07001055 repo_messages.reverse()
James E. Blairc6294a52012-08-17 10:19:48 -07001056 correct_messages = ['initial commit', 'mp commit', 'B-1']
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001057 self.assertEqual(repo_messages, correct_messages)
James E. Blairbb1fe502014-03-04 10:15:06 -08001058 self.assertEqual(repo_shas[0], commit_B)
1059
1060 repo_messages = [c.message.strip()
1061 for c in repo.iter_commits(ref_A)]
1062 repo_shas = [c.hexsha for c in repo.iter_commits(ref_A)]
1063 repo_messages.reverse()
1064 correct_messages = ['initial commit', 'A-1']
1065 self.assertEqual(repo_messages, correct_messages)
1066 self.assertEqual(repo_shas[0], commit_A)
1067
1068 self.assertNotEqual(ref_A, ref_B, ref_C)
1069 self.assertNotEqual(commit_A, commit_B, commit_C)
James E. Blair7f71c802012-08-22 13:04:32 -07001070
1071 def test_one_job_project(self):
1072 "Test that queueing works with one job"
1073 A = self.fake_gerrit.addFakeChange('org/one-job-project',
1074 'master', 'A')
1075 B = self.fake_gerrit.addFakeChange('org/one-job-project',
1076 'master', 'B')
1077 A.addApproval('CRVW', 2)
1078 B.addApproval('CRVW', 2)
1079 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1080 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1081 self.waitUntilSettled()
1082
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001083 self.assertEqual(A.data['status'], 'MERGED')
1084 self.assertEqual(A.reported, 2)
1085 self.assertEqual(B.data['status'], 'MERGED')
1086 self.assertEqual(B.reported, 2)
James E. Blaircaec0c52012-08-22 14:52:22 -07001087
Antoine Musso80edd5a2013-02-13 15:37:53 +01001088 def test_job_from_templates_launched(self):
1089 "Test whether a job generated via a template can be launched"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001090
Antoine Musso80edd5a2013-02-13 15:37:53 +01001091 A = self.fake_gerrit.addFakeChange(
1092 'org/templated-project', 'master', 'A')
1093 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1094 self.waitUntilSettled()
Antoine Musso80edd5a2013-02-13 15:37:53 +01001095
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001096 self.assertEqual(self.getJobFromHistory('project-test1').result,
1097 'SUCCESS')
1098 self.assertEqual(self.getJobFromHistory('project-test2').result,
1099 'SUCCESS')
Antoine Musso80edd5a2013-02-13 15:37:53 +01001100
James E. Blair3e98c022013-12-16 15:25:38 -08001101 def test_layered_templates(self):
1102 "Test whether a job generated via a template can be launched"
1103
1104 A = self.fake_gerrit.addFakeChange(
1105 'org/layered-project', 'master', 'A')
1106 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1107 self.waitUntilSettled()
1108
1109 self.assertEqual(self.getJobFromHistory('project-test1').result,
1110 'SUCCESS')
1111 self.assertEqual(self.getJobFromHistory('project-test2').result,
1112 'SUCCESS')
James E. Blairaea6cf62013-12-16 15:38:12 -08001113 self.assertEqual(self.getJobFromHistory('layered-project-test3'
1114 ).result, 'SUCCESS')
1115 self.assertEqual(self.getJobFromHistory('layered-project-test4'
1116 ).result, 'SUCCESS')
James E. Blair12a92b12014-03-26 11:54:53 -07001117 self.assertEqual(self.getJobFromHistory('layered-project-foo-test5'
1118 ).result, 'SUCCESS')
James E. Blair3e98c022013-12-16 15:25:38 -08001119 self.assertEqual(self.getJobFromHistory('project-test6').result,
1120 'SUCCESS')
1121
James E. Blaircaec0c52012-08-22 14:52:22 -07001122 def test_dependent_changes_dequeue(self):
1123 "Test that dependent patches are not needlessly tested"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001124
James E. Blaircaec0c52012-08-22 14:52:22 -07001125 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1126 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1127 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1128 A.addApproval('CRVW', 2)
1129 B.addApproval('CRVW', 2)
1130 C.addApproval('CRVW', 2)
1131
1132 M1 = self.fake_gerrit.addFakeChange('org/project', 'master', 'M1')
1133 M1.setMerged()
1134
1135 # C -> B -> A -> M1
1136
1137 C.setDependsOn(B, 1)
1138 B.setDependsOn(A, 1)
1139 A.setDependsOn(M1, 1)
1140
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001141 self.worker.addFailTest('project-merge', A)
James E. Blaircaec0c52012-08-22 14:52:22 -07001142
1143 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1144 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1145 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1146
1147 self.waitUntilSettled()
1148
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001149 self.assertEqual(A.data['status'], 'NEW')
1150 self.assertEqual(A.reported, 2)
1151 self.assertEqual(B.data['status'], 'NEW')
1152 self.assertEqual(B.reported, 2)
1153 self.assertEqual(C.data['status'], 'NEW')
1154 self.assertEqual(C.reported, 2)
1155 self.assertEqual(len(self.history), 1)
James E. Blairec590122012-08-22 15:19:31 -07001156
James E. Blair972e3c72013-08-29 12:04:55 -07001157 def test_failing_dependent_changes(self):
1158 "Test that failing dependent patches are taken out of stream"
1159 self.worker.hold_jobs_in_build = True
1160 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1161 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1162 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1163 D = self.fake_gerrit.addFakeChange('org/project', 'master', 'D')
1164 E = self.fake_gerrit.addFakeChange('org/project', 'master', 'E')
1165 A.addApproval('CRVW', 2)
1166 B.addApproval('CRVW', 2)
1167 C.addApproval('CRVW', 2)
1168 D.addApproval('CRVW', 2)
1169 E.addApproval('CRVW', 2)
1170
1171 # E, D -> C -> B, A
1172
1173 D.setDependsOn(C, 1)
1174 C.setDependsOn(B, 1)
1175
1176 self.worker.addFailTest('project-test1', B)
1177
1178 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1179 self.fake_gerrit.addEvent(D.addApproval('APRV', 1))
1180 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1181 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1182 self.fake_gerrit.addEvent(E.addApproval('APRV', 1))
1183
1184 self.waitUntilSettled()
1185 self.worker.release('.*-merge')
1186 self.waitUntilSettled()
1187 self.worker.release('.*-merge')
1188 self.waitUntilSettled()
1189 self.worker.release('.*-merge')
1190 self.waitUntilSettled()
1191 self.worker.release('.*-merge')
1192 self.waitUntilSettled()
1193 self.worker.release('.*-merge')
1194 self.waitUntilSettled()
1195
1196 self.worker.hold_jobs_in_build = False
1197 for build in self.builds:
1198 if build.parameters['ZUUL_CHANGE'] != '1':
1199 build.release()
1200 self.waitUntilSettled()
1201
1202 self.worker.release()
1203 self.waitUntilSettled()
1204
1205 self.assertEqual(A.data['status'], 'MERGED')
1206 self.assertEqual(A.reported, 2)
Jeremy Stanley10837132014-08-02 16:10:56 +00001207 self.assertIn('Build succeeded', A.messages[1])
James E. Blair972e3c72013-08-29 12:04:55 -07001208 self.assertEqual(B.data['status'], 'NEW')
1209 self.assertEqual(B.reported, 2)
Jeremy Stanley10837132014-08-02 16:10:56 +00001210 self.assertIn('Build failed', B.messages[1])
James E. Blair972e3c72013-08-29 12:04:55 -07001211 self.assertEqual(C.data['status'], 'NEW')
1212 self.assertEqual(C.reported, 2)
Jeremy Stanley10837132014-08-02 16:10:56 +00001213 self.assertIn('depends on a change', C.messages[1])
James E. Blair972e3c72013-08-29 12:04:55 -07001214 self.assertEqual(D.data['status'], 'NEW')
1215 self.assertEqual(D.reported, 2)
Jeremy Stanley10837132014-08-02 16:10:56 +00001216 self.assertIn('depends on a change', D.messages[1])
James E. Blair972e3c72013-08-29 12:04:55 -07001217 self.assertEqual(E.data['status'], 'MERGED')
1218 self.assertEqual(E.reported, 2)
Jeremy Stanley10837132014-08-02 16:10:56 +00001219 self.assertIn('Build succeeded', E.messages[1])
James E. Blair972e3c72013-08-29 12:04:55 -07001220 self.assertEqual(len(self.history), 18)
1221
James E. Blairec590122012-08-22 15:19:31 -07001222 def test_head_is_dequeued_once(self):
James E. Blair2fa50962013-01-30 21:50:41 -08001223 "Test that if a change at the head fails it is dequeued only once"
James E. Blairec590122012-08-22 15:19:31 -07001224 # If it's dequeued more than once, we should see extra
1225 # aborted jobs.
James E. Blairec590122012-08-22 15:19:31 -07001226
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001227 self.worker.hold_jobs_in_build = True
James E. Blairec590122012-08-22 15:19:31 -07001228 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
1229 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
1230 C = self.fake_gerrit.addFakeChange('org/project1', 'master', 'C')
1231 A.addApproval('CRVW', 2)
1232 B.addApproval('CRVW', 2)
1233 C.addApproval('CRVW', 2)
1234
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001235 self.worker.addFailTest('project1-test1', A)
1236 self.worker.addFailTest('project1-test2', A)
1237 self.worker.addFailTest('project1-project2-integration', A)
James E. Blairec590122012-08-22 15:19:31 -07001238
1239 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1240 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1241 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1242
1243 self.waitUntilSettled()
James E. Blairec590122012-08-22 15:19:31 -07001244
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001245 self.assertEqual(len(self.builds), 1)
1246 self.assertEqual(self.builds[0].name, 'project1-merge')
1247 self.assertTrue(self.job_has_changes(self.builds[0], A))
James E. Blairec590122012-08-22 15:19:31 -07001248
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001249 self.worker.release('.*-merge')
James E. Blairec590122012-08-22 15:19:31 -07001250 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001251 self.worker.release('.*-merge')
James E. Blairec590122012-08-22 15:19:31 -07001252 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001253 self.worker.release('.*-merge')
James E. Blairec590122012-08-22 15:19:31 -07001254 self.waitUntilSettled()
1255
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001256 self.assertEqual(len(self.builds), 9)
1257 self.assertEqual(self.builds[0].name, 'project1-test1')
1258 self.assertEqual(self.builds[1].name, 'project1-test2')
1259 self.assertEqual(self.builds[2].name, 'project1-project2-integration')
1260 self.assertEqual(self.builds[3].name, 'project1-test1')
1261 self.assertEqual(self.builds[4].name, 'project1-test2')
1262 self.assertEqual(self.builds[5].name, 'project1-project2-integration')
1263 self.assertEqual(self.builds[6].name, 'project1-test1')
1264 self.assertEqual(self.builds[7].name, 'project1-test2')
1265 self.assertEqual(self.builds[8].name, 'project1-project2-integration')
James E. Blairec590122012-08-22 15:19:31 -07001266
Monty Taylor6bef8ef2013-06-02 08:17:12 -04001267 self.release(self.builds[0])
James E. Blairec590122012-08-22 15:19:31 -07001268 self.waitUntilSettled()
1269
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001270 self.assertEqual(len(self.builds), 3) # test2,integration, merge for B
1271 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 6)
James E. Blairec590122012-08-22 15:19:31 -07001272
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001273 self.worker.hold_jobs_in_build = False
1274 self.worker.release()
James E. Blairec590122012-08-22 15:19:31 -07001275 self.waitUntilSettled()
1276
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001277 self.assertEqual(len(self.builds), 0)
1278 self.assertEqual(len(self.history), 20)
James E. Blaircaec0c52012-08-22 14:52:22 -07001279
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001280 self.assertEqual(A.data['status'], 'NEW')
1281 self.assertEqual(B.data['status'], 'MERGED')
1282 self.assertEqual(C.data['status'], 'MERGED')
1283 self.assertEqual(A.reported, 2)
1284 self.assertEqual(B.reported, 2)
1285 self.assertEqual(C.reported, 2)
James E. Blair4ec821f2012-08-23 15:28:28 -07001286
1287 def test_nonvoting_job(self):
1288 "Test that non-voting jobs don't vote."
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001289
James E. Blair4ec821f2012-08-23 15:28:28 -07001290 A = self.fake_gerrit.addFakeChange('org/nonvoting-project',
1291 'master', 'A')
1292 A.addApproval('CRVW', 2)
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001293 self.worker.addFailTest('nonvoting-project-test2', A)
James E. Blair4ec821f2012-08-23 15:28:28 -07001294 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1295
1296 self.waitUntilSettled()
James E. Blair4ec821f2012-08-23 15:28:28 -07001297
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001298 self.assertEqual(A.data['status'], 'MERGED')
1299 self.assertEqual(A.reported, 2)
1300 self.assertEqual(
1301 self.getJobFromHistory('nonvoting-project-merge').result,
1302 'SUCCESS')
1303 self.assertEqual(
1304 self.getJobFromHistory('nonvoting-project-test1').result,
1305 'SUCCESS')
1306 self.assertEqual(
1307 self.getJobFromHistory('nonvoting-project-test2').result,
1308 'FAILURE')
James E. Blaire0487072012-08-29 17:38:31 -07001309
James E. Blair5821bd92015-09-16 08:48:15 -07001310 for build in self.builds:
1311 self.assertEqual(build.parameters['ZUUL_VOTING'], '0')
1312
James E. Blaire0487072012-08-29 17:38:31 -07001313 def test_check_queue_success(self):
1314 "Test successful check queue jobs."
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001315
James E. Blaire0487072012-08-29 17:38:31 -07001316 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1317 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1318
1319 self.waitUntilSettled()
James E. Blaire0487072012-08-29 17:38:31 -07001320
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001321 self.assertEqual(A.data['status'], 'NEW')
1322 self.assertEqual(A.reported, 1)
1323 self.assertEqual(self.getJobFromHistory('project-merge').result,
1324 'SUCCESS')
1325 self.assertEqual(self.getJobFromHistory('project-test1').result,
1326 'SUCCESS')
1327 self.assertEqual(self.getJobFromHistory('project-test2').result,
1328 'SUCCESS')
James E. Blaire0487072012-08-29 17:38:31 -07001329
1330 def test_check_queue_failure(self):
1331 "Test failed check queue jobs."
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001332
James E. Blaire0487072012-08-29 17:38:31 -07001333 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001334 self.worker.addFailTest('project-test2', A)
James E. Blaire0487072012-08-29 17:38:31 -07001335 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1336
1337 self.waitUntilSettled()
James E. Blaire0487072012-08-29 17:38:31 -07001338
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001339 self.assertEqual(A.data['status'], 'NEW')
1340 self.assertEqual(A.reported, 1)
1341 self.assertEqual(self.getJobFromHistory('project-merge').result,
James E. Blair78e31b32013-07-09 09:11:34 -07001342 'SUCCESS')
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001343 self.assertEqual(self.getJobFromHistory('project-test1').result,
1344 'SUCCESS')
1345 self.assertEqual(self.getJobFromHistory('project-test2').result,
1346 'FAILURE')
James E. Blair127bc182012-08-28 15:55:15 -07001347
1348 def test_dependent_behind_dequeue(self):
1349 "test that dependent changes behind dequeued changes work"
1350 # This complicated test is a reproduction of a real life bug
1351 self.sched.reconfigure(self.config)
James E. Blair127bc182012-08-28 15:55:15 -07001352
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001353 self.worker.hold_jobs_in_build = True
James E. Blair127bc182012-08-28 15:55:15 -07001354 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
1355 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
1356 C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
1357 D = self.fake_gerrit.addFakeChange('org/project2', 'master', 'D')
1358 E = self.fake_gerrit.addFakeChange('org/project2', 'master', 'E')
1359 F = self.fake_gerrit.addFakeChange('org/project3', 'master', 'F')
1360 D.setDependsOn(C, 1)
1361 E.setDependsOn(D, 1)
1362 A.addApproval('CRVW', 2)
1363 B.addApproval('CRVW', 2)
1364 C.addApproval('CRVW', 2)
1365 D.addApproval('CRVW', 2)
1366 E.addApproval('CRVW', 2)
1367 F.addApproval('CRVW', 2)
1368
1369 A.fail_merge = True
James E. Blair127bc182012-08-28 15:55:15 -07001370
1371 # Change object re-use in the gerrit trigger is hidden if
1372 # changes are added in quick succession; waiting makes it more
1373 # like real life.
1374 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1375 self.waitUntilSettled()
1376 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1377 self.waitUntilSettled()
1378
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001379 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001380 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001381 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001382 self.waitUntilSettled()
1383
1384 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1385 self.waitUntilSettled()
1386 self.fake_gerrit.addEvent(D.addApproval('APRV', 1))
1387 self.waitUntilSettled()
1388 self.fake_gerrit.addEvent(E.addApproval('APRV', 1))
1389 self.waitUntilSettled()
1390 self.fake_gerrit.addEvent(F.addApproval('APRV', 1))
1391 self.waitUntilSettled()
1392
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001393 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001394 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001395 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001396 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001397 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001398 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001399 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001400 self.waitUntilSettled()
1401
1402 # all jobs running
James E. Blaire955e062012-10-08 09:49:03 -07001403
1404 # Grab pointers to the jobs we want to release before
1405 # releasing any, because list indexes may change as
1406 # the jobs complete.
Monty Taylor6bef8ef2013-06-02 08:17:12 -04001407 a, b, c = self.builds[:3]
James E. Blaire955e062012-10-08 09:49:03 -07001408 a.release()
1409 b.release()
1410 c.release()
James E. Blair127bc182012-08-28 15:55:15 -07001411 self.waitUntilSettled()
1412
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001413 self.worker.hold_jobs_in_build = False
1414 self.worker.release()
James E. Blair127bc182012-08-28 15:55:15 -07001415 self.waitUntilSettled()
1416
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001417 self.assertEqual(A.data['status'], 'NEW')
1418 self.assertEqual(B.data['status'], 'MERGED')
1419 self.assertEqual(C.data['status'], 'MERGED')
1420 self.assertEqual(D.data['status'], 'MERGED')
1421 self.assertEqual(E.data['status'], 'MERGED')
1422 self.assertEqual(F.data['status'], 'MERGED')
James E. Blair127bc182012-08-28 15:55:15 -07001423
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001424 self.assertEqual(A.reported, 2)
1425 self.assertEqual(B.reported, 2)
1426 self.assertEqual(C.reported, 2)
1427 self.assertEqual(D.reported, 2)
1428 self.assertEqual(E.reported, 2)
1429 self.assertEqual(F.reported, 2)
James E. Blair127bc182012-08-28 15:55:15 -07001430
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001431 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 15)
1432 self.assertEqual(len(self.history), 44)
James E. Blair05fed602012-09-07 12:45:24 -07001433
1434 def test_merger_repack(self):
1435 "Test that the merger works after a repack"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001436
James E. Blair05fed602012-09-07 12:45:24 -07001437 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1438 A.addApproval('CRVW', 2)
1439 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1440 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001441 self.assertEqual(self.getJobFromHistory('project-merge').result,
1442 'SUCCESS')
1443 self.assertEqual(self.getJobFromHistory('project-test1').result,
1444 'SUCCESS')
1445 self.assertEqual(self.getJobFromHistory('project-test2').result,
1446 'SUCCESS')
1447 self.assertEqual(A.data['status'], 'MERGED')
1448 self.assertEqual(A.reported, 2)
James E. Blair05fed602012-09-07 12:45:24 -07001449 self.assertEmptyQueues()
James E. Blair4ca985f2013-05-30 12:27:43 -07001450 self.worker.build_history = []
James E. Blair05fed602012-09-07 12:45:24 -07001451
Monty Taylorbc758832013-06-17 17:22:42 -04001452 path = os.path.join(self.git_root, "org/project")
1453 print repack_repo(path)
James E. Blair05fed602012-09-07 12:45:24 -07001454
1455 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1456 A.addApproval('CRVW', 2)
1457 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1458 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001459 self.assertEqual(self.getJobFromHistory('project-merge').result,
1460 'SUCCESS')
1461 self.assertEqual(self.getJobFromHistory('project-test1').result,
1462 'SUCCESS')
1463 self.assertEqual(self.getJobFromHistory('project-test2').result,
1464 'SUCCESS')
1465 self.assertEqual(A.data['status'], 'MERGED')
1466 self.assertEqual(A.reported, 2)
James E. Blair7ee88a22012-09-12 18:59:31 +02001467
James E. Blair4886f282012-11-15 09:27:33 -08001468 def test_merger_repack_large_change(self):
1469 "Test that the merger works with large changes after a repack"
1470 # https://bugs.launchpad.net/zuul/+bug/1078946
James E. Blairac2c3242014-01-24 13:38:51 -08001471 # This test assumes the repo is already cloned; make sure it is
Joshua Hesketh352264b2015-08-11 23:42:08 +10001472 url = self.fake_gerrit.getGitUrl(
James E. Blairac2c3242014-01-24 13:38:51 -08001473 self.sched.layout.projects['org/project1'])
James E. Blair4076e2b2014-01-28 12:42:20 -08001474 self.merge_server.merger.addProject('org/project1', url)
James E. Blair4886f282012-11-15 09:27:33 -08001475 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
1476 A.addPatchset(large=True)
Monty Taylorbc758832013-06-17 17:22:42 -04001477 path = os.path.join(self.upstream_root, "org/project1")
1478 print repack_repo(path)
1479 path = os.path.join(self.git_root, "org/project1")
1480 print repack_repo(path)
James E. Blair4886f282012-11-15 09:27:33 -08001481
1482 A.addApproval('CRVW', 2)
1483 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1484 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001485 self.assertEqual(self.getJobFromHistory('project1-merge').result,
1486 'SUCCESS')
1487 self.assertEqual(self.getJobFromHistory('project1-test1').result,
1488 'SUCCESS')
1489 self.assertEqual(self.getJobFromHistory('project1-test2').result,
1490 'SUCCESS')
1491 self.assertEqual(A.data['status'], 'MERGED')
1492 self.assertEqual(A.reported, 2)
James E. Blair4886f282012-11-15 09:27:33 -08001493
James E. Blair7ee88a22012-09-12 18:59:31 +02001494 def test_nonexistent_job(self):
1495 "Test launching a job that doesn't exist"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001496 # Set to the state immediately after a restart
1497 self.resetGearmanServer()
1498 self.launcher.negative_function_cache_ttl = 0
James E. Blair7ee88a22012-09-12 18:59:31 +02001499
1500 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1501 A.addApproval('CRVW', 2)
1502 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1503 # There may be a thread about to report a lost change
1504 while A.reported < 2:
1505 self.waitUntilSettled()
Monty Taylor6bef8ef2013-06-02 08:17:12 -04001506 job_names = [x.name for x in self.history]
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001507 self.assertFalse(job_names)
1508 self.assertEqual(A.data['status'], 'NEW')
1509 self.assertEqual(A.reported, 2)
James E. Blair7ee88a22012-09-12 18:59:31 +02001510 self.assertEmptyQueues()
1511
1512 # Make sure things still work:
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001513 self.registerJobs()
James E. Blair7ee88a22012-09-12 18:59:31 +02001514 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1515 A.addApproval('CRVW', 2)
1516 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1517 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001518 self.assertEqual(self.getJobFromHistory('project-merge').result,
1519 'SUCCESS')
1520 self.assertEqual(self.getJobFromHistory('project-test1').result,
1521 'SUCCESS')
1522 self.assertEqual(self.getJobFromHistory('project-test2').result,
1523 'SUCCESS')
1524 self.assertEqual(A.data['status'], 'MERGED')
1525 self.assertEqual(A.reported, 2)
James E. Blairf62d4282012-12-31 17:01:50 -08001526
1527 def test_single_nonexistent_post_job(self):
1528 "Test launching a single post job that doesn't exist"
James E. Blairf62d4282012-12-31 17:01:50 -08001529 e = {
1530 "type": "ref-updated",
1531 "submitter": {
1532 "name": "User Name",
1533 },
1534 "refUpdate": {
1535 "oldRev": "90f173846e3af9154517b88543ffbd1691f31366",
1536 "newRev": "d479a0bfcb34da57a31adb2a595c0cf687812543",
1537 "refName": "master",
1538 "project": "org/project",
1539 }
1540 }
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001541 # Set to the state immediately after a restart
1542 self.resetGearmanServer()
1543 self.launcher.negative_function_cache_ttl = 0
1544
James E. Blairf62d4282012-12-31 17:01:50 -08001545 self.fake_gerrit.addEvent(e)
1546 self.waitUntilSettled()
1547
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001548 self.assertEqual(len(self.history), 0)
James E. Blair2fa50962013-01-30 21:50:41 -08001549
1550 def test_new_patchset_dequeues_old(self):
1551 "Test that a new patchset causes the old to be dequeued"
1552 # D -> C (depends on B) -> B (depends on A) -> A -> M
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001553 self.worker.hold_jobs_in_build = True
James E. Blair2fa50962013-01-30 21:50:41 -08001554 M = self.fake_gerrit.addFakeChange('org/project', 'master', 'M')
1555 M.setMerged()
1556
1557 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1558 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1559 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1560 D = self.fake_gerrit.addFakeChange('org/project', 'master', 'D')
1561 A.addApproval('CRVW', 2)
1562 B.addApproval('CRVW', 2)
1563 C.addApproval('CRVW', 2)
1564 D.addApproval('CRVW', 2)
1565
1566 C.setDependsOn(B, 1)
1567 B.setDependsOn(A, 1)
1568 A.setDependsOn(M, 1)
1569
1570 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1571 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1572 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1573 self.fake_gerrit.addEvent(D.addApproval('APRV', 1))
1574 self.waitUntilSettled()
1575
1576 B.addPatchset()
1577 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(2))
1578 self.waitUntilSettled()
1579
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001580 self.worker.hold_jobs_in_build = False
1581 self.worker.release()
James E. Blair2fa50962013-01-30 21:50:41 -08001582 self.waitUntilSettled()
1583
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001584 self.assertEqual(A.data['status'], 'MERGED')
1585 self.assertEqual(A.reported, 2)
1586 self.assertEqual(B.data['status'], 'NEW')
1587 self.assertEqual(B.reported, 2)
1588 self.assertEqual(C.data['status'], 'NEW')
1589 self.assertEqual(C.reported, 2)
1590 self.assertEqual(D.data['status'], 'MERGED')
1591 self.assertEqual(D.reported, 2)
1592 self.assertEqual(len(self.history), 9) # 3 each for A, B, D.
James E. Blair2fa50962013-01-30 21:50:41 -08001593
James E. Blairba437362015-02-07 11:41:52 -08001594 def test_new_patchset_check(self):
1595 "Test a new patchset in check"
Antoine Mussobd86a312014-01-08 14:51:33 +01001596
1597 self.worker.hold_jobs_in_build = True
1598
1599 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
James E. Blairba437362015-02-07 11:41:52 -08001600 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1601 check_pipeline = self.sched.layout.pipelines['check']
1602
1603 # Add two git-dependent changes
1604 B.setDependsOn(A, 1)
1605 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1606 self.waitUntilSettled()
Antoine Mussobd86a312014-01-08 14:51:33 +01001607 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1608 self.waitUntilSettled()
James E. Blairba437362015-02-07 11:41:52 -08001609
1610 # A live item, and a non-live/live pair
1611 items = check_pipeline.getAllItems()
1612 self.assertEqual(len(items), 3)
1613
1614 self.assertEqual(items[0].change.number, '1')
1615 self.assertEqual(items[0].change.patchset, '1')
1616 self.assertFalse(items[0].live)
1617
1618 self.assertEqual(items[1].change.number, '2')
1619 self.assertEqual(items[1].change.patchset, '1')
1620 self.assertTrue(items[1].live)
1621
1622 self.assertEqual(items[2].change.number, '1')
1623 self.assertEqual(items[2].change.patchset, '1')
1624 self.assertTrue(items[2].live)
1625
1626 # Add a new patchset to A
1627 A.addPatchset()
1628 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
1629 self.waitUntilSettled()
1630
1631 # The live copy of A,1 should be gone, but the non-live and B
1632 # should continue, and we should have a new A,2
1633 items = check_pipeline.getAllItems()
1634 self.assertEqual(len(items), 3)
1635
1636 self.assertEqual(items[0].change.number, '1')
1637 self.assertEqual(items[0].change.patchset, '1')
1638 self.assertFalse(items[0].live)
1639
1640 self.assertEqual(items[1].change.number, '2')
1641 self.assertEqual(items[1].change.patchset, '1')
1642 self.assertTrue(items[1].live)
1643
1644 self.assertEqual(items[2].change.number, '1')
1645 self.assertEqual(items[2].change.patchset, '2')
1646 self.assertTrue(items[2].live)
1647
1648 # Add a new patchset to B
1649 B.addPatchset()
1650 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(2))
1651 self.waitUntilSettled()
1652
1653 # The live copy of B,1 should be gone, and it's non-live copy of A,1
1654 # but we should have a new B,2 (still based on A,1)
1655 items = check_pipeline.getAllItems()
1656 self.assertEqual(len(items), 3)
1657
1658 self.assertEqual(items[0].change.number, '1')
1659 self.assertEqual(items[0].change.patchset, '2')
1660 self.assertTrue(items[0].live)
1661
1662 self.assertEqual(items[1].change.number, '1')
1663 self.assertEqual(items[1].change.patchset, '1')
1664 self.assertFalse(items[1].live)
1665
1666 self.assertEqual(items[2].change.number, '2')
1667 self.assertEqual(items[2].change.patchset, '2')
1668 self.assertTrue(items[2].live)
1669
1670 self.builds[0].release()
1671 self.waitUntilSettled()
1672 self.builds[0].release()
1673 self.waitUntilSettled()
1674 self.worker.hold_jobs_in_build = False
1675 self.worker.release()
1676 self.waitUntilSettled()
1677
1678 self.assertEqual(A.reported, 1)
1679 self.assertEqual(B.reported, 1)
1680 self.assertEqual(self.history[0].result, 'ABORTED')
1681 self.assertEqual(self.history[0].changes, '1,1')
1682 self.assertEqual(self.history[1].result, 'ABORTED')
1683 self.assertEqual(self.history[1].changes, '1,1 2,1')
1684 self.assertEqual(self.history[2].result, 'SUCCESS')
1685 self.assertEqual(self.history[2].changes, '1,2')
1686 self.assertEqual(self.history[3].result, 'SUCCESS')
1687 self.assertEqual(self.history[3].changes, '1,1 2,2')
1688
1689 def test_abandoned_gate(self):
1690 "Test that an abandoned change is dequeued from gate"
1691
1692 self.worker.hold_jobs_in_build = True
1693
1694 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1695 A.addApproval('CRVW', 2)
1696 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1697 self.waitUntilSettled()
Antoine Mussobd86a312014-01-08 14:51:33 +01001698 self.assertEqual(len(self.builds), 1, "One job being built (on hold)")
1699 self.assertEqual(self.builds[0].name, 'project-merge')
1700
1701 self.fake_gerrit.addEvent(A.getChangeAbandonedEvent())
1702 self.waitUntilSettled()
1703
Antoine Mussobd86a312014-01-08 14:51:33 +01001704 self.worker.release('.*-merge')
1705 self.waitUntilSettled()
1706
1707 self.assertEqual(len(self.builds), 0, "No job running")
Antoine Mussobd86a312014-01-08 14:51:33 +01001708 self.assertEqual(len(self.history), 1, "Only one build in history")
1709 self.assertEqual(self.history[0].result, 'ABORTED',
James E. Blairba437362015-02-07 11:41:52 -08001710 "Build should have been aborted")
1711 self.assertEqual(A.reported, 1,
1712 "Abandoned gate change should report only start")
1713
1714 def test_abandoned_check(self):
1715 "Test that an abandoned change is dequeued from check"
1716
1717 self.worker.hold_jobs_in_build = True
1718
1719 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1720 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1721 check_pipeline = self.sched.layout.pipelines['check']
1722
1723 # Add two git-dependent changes
1724 B.setDependsOn(A, 1)
1725 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1726 self.waitUntilSettled()
1727 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1728 self.waitUntilSettled()
1729 # A live item, and a non-live/live pair
1730 items = check_pipeline.getAllItems()
1731 self.assertEqual(len(items), 3)
1732
1733 self.assertEqual(items[0].change.number, '1')
1734 self.assertFalse(items[0].live)
1735
1736 self.assertEqual(items[1].change.number, '2')
1737 self.assertTrue(items[1].live)
1738
1739 self.assertEqual(items[2].change.number, '1')
1740 self.assertTrue(items[2].live)
1741
1742 # Abandon A
1743 self.fake_gerrit.addEvent(A.getChangeAbandonedEvent())
1744 self.waitUntilSettled()
1745
1746 # The live copy of A should be gone, but the non-live and B
1747 # should continue
1748 items = check_pipeline.getAllItems()
1749 self.assertEqual(len(items), 2)
1750
1751 self.assertEqual(items[0].change.number, '1')
1752 self.assertFalse(items[0].live)
1753
1754 self.assertEqual(items[1].change.number, '2')
1755 self.assertTrue(items[1].live)
1756
1757 self.worker.hold_jobs_in_build = False
1758 self.worker.release()
1759 self.waitUntilSettled()
1760
1761 self.assertEqual(len(self.history), 4)
1762 self.assertEqual(self.history[0].result, 'ABORTED',
Antoine Mussobd86a312014-01-08 14:51:33 +01001763 'Build should have been aborted')
1764 self.assertEqual(A.reported, 0, "Abandoned change should not report")
James E. Blairba437362015-02-07 11:41:52 -08001765 self.assertEqual(B.reported, 1, "Change should report")
Antoine Mussobd86a312014-01-08 14:51:33 +01001766
Steve Varnau7b78b312015-04-03 14:49:46 -07001767 def test_abandoned_not_timer(self):
1768 "Test that an abandoned change does not cancel timer jobs"
1769
1770 self.worker.hold_jobs_in_build = True
1771
1772 # Start timer trigger - also org/project
1773 self.config.set('zuul', 'layout_config',
1774 'tests/fixtures/layout-idle.yaml')
1775 self.sched.reconfigure(self.config)
1776 self.registerJobs()
1777 # The pipeline triggers every second, so we should have seen
1778 # several by now.
1779 time.sleep(5)
1780 self.waitUntilSettled()
1781 # Stop queuing timer triggered jobs so that the assertions
1782 # below don't race against more jobs being queued.
1783 self.config.set('zuul', 'layout_config',
1784 'tests/fixtures/layout-no-timer.yaml')
1785 self.sched.reconfigure(self.config)
1786 self.registerJobs()
1787 self.assertEqual(len(self.builds), 2, "Two timer jobs")
1788
1789 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1790 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1791 self.waitUntilSettled()
1792 self.assertEqual(len(self.builds), 3, "One change plus two timer jobs")
1793
1794 self.fake_gerrit.addEvent(A.getChangeAbandonedEvent())
1795 self.waitUntilSettled()
1796
1797 self.assertEqual(len(self.builds), 2, "Two timer jobs remain")
1798
1799 self.worker.release()
1800 self.waitUntilSettled()
1801
Arx Cruzb1b010d2013-10-28 19:49:59 -02001802 def test_zuul_url_return(self):
1803 "Test if ZUUL_URL is returning when zuul_url is set in zuul.conf"
James E. Blair4076e2b2014-01-28 12:42:20 -08001804 self.assertTrue(self.sched.config.has_option('merger', 'zuul_url'))
Arx Cruzb1b010d2013-10-28 19:49:59 -02001805 self.worker.hold_jobs_in_build = True
1806
1807 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1808 A.addApproval('CRVW', 2)
1809 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1810 self.waitUntilSettled()
1811
1812 self.assertEqual(len(self.builds), 1)
1813 for build in self.builds:
1814 self.assertTrue('ZUUL_URL' in build.parameters)
1815
1816 self.worker.hold_jobs_in_build = False
1817 self.worker.release()
1818 self.waitUntilSettled()
1819
James E. Blair2fa50962013-01-30 21:50:41 -08001820 def test_new_patchset_dequeues_old_on_head(self):
1821 "Test that a new patchset causes the old to be dequeued (at head)"
1822 # D -> C (depends on B) -> B (depends on A) -> A -> M
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001823 self.worker.hold_jobs_in_build = True
James E. Blair2fa50962013-01-30 21:50:41 -08001824 M = self.fake_gerrit.addFakeChange('org/project', 'master', 'M')
1825 M.setMerged()
1826 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1827 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1828 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1829 D = self.fake_gerrit.addFakeChange('org/project', 'master', 'D')
1830 A.addApproval('CRVW', 2)
1831 B.addApproval('CRVW', 2)
1832 C.addApproval('CRVW', 2)
1833 D.addApproval('CRVW', 2)
1834
1835 C.setDependsOn(B, 1)
1836 B.setDependsOn(A, 1)
1837 A.setDependsOn(M, 1)
1838
1839 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1840 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1841 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1842 self.fake_gerrit.addEvent(D.addApproval('APRV', 1))
1843 self.waitUntilSettled()
1844
1845 A.addPatchset()
1846 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
1847 self.waitUntilSettled()
1848
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001849 self.worker.hold_jobs_in_build = False
1850 self.worker.release()
James E. Blair2fa50962013-01-30 21:50:41 -08001851 self.waitUntilSettled()
1852
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001853 self.assertEqual(A.data['status'], 'NEW')
1854 self.assertEqual(A.reported, 2)
1855 self.assertEqual(B.data['status'], 'NEW')
1856 self.assertEqual(B.reported, 2)
1857 self.assertEqual(C.data['status'], 'NEW')
1858 self.assertEqual(C.reported, 2)
1859 self.assertEqual(D.data['status'], 'MERGED')
1860 self.assertEqual(D.reported, 2)
1861 self.assertEqual(len(self.history), 7)
James E. Blair2fa50962013-01-30 21:50:41 -08001862
1863 def test_new_patchset_dequeues_old_without_dependents(self):
1864 "Test that a new patchset causes only the old to be dequeued"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001865 self.worker.hold_jobs_in_build = True
James E. Blair2fa50962013-01-30 21:50:41 -08001866 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1867 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1868 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1869 A.addApproval('CRVW', 2)
1870 B.addApproval('CRVW', 2)
1871 C.addApproval('CRVW', 2)
1872
1873 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1874 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1875 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1876 self.waitUntilSettled()
1877
1878 B.addPatchset()
1879 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(2))
1880 self.waitUntilSettled()
1881
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001882 self.worker.hold_jobs_in_build = False
1883 self.worker.release()
James E. Blair2fa50962013-01-30 21:50:41 -08001884 self.waitUntilSettled()
1885
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001886 self.assertEqual(A.data['status'], 'MERGED')
1887 self.assertEqual(A.reported, 2)
1888 self.assertEqual(B.data['status'], 'NEW')
1889 self.assertEqual(B.reported, 2)
1890 self.assertEqual(C.data['status'], 'MERGED')
1891 self.assertEqual(C.reported, 2)
1892 self.assertEqual(len(self.history), 9)
James E. Blair2fa50962013-01-30 21:50:41 -08001893
1894 def test_new_patchset_dequeues_old_independent_queue(self):
1895 "Test that a new patchset causes the old to be dequeued (independent)"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001896 self.worker.hold_jobs_in_build = True
James E. Blair2fa50962013-01-30 21:50:41 -08001897 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1898 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1899 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1900 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1901 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1902 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
1903 self.waitUntilSettled()
1904
1905 B.addPatchset()
1906 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(2))
1907 self.waitUntilSettled()
1908
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001909 self.worker.hold_jobs_in_build = False
1910 self.worker.release()
James E. Blair2fa50962013-01-30 21:50:41 -08001911 self.waitUntilSettled()
1912
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001913 self.assertEqual(A.data['status'], 'NEW')
1914 self.assertEqual(A.reported, 1)
1915 self.assertEqual(B.data['status'], 'NEW')
1916 self.assertEqual(B.reported, 1)
1917 self.assertEqual(C.data['status'], 'NEW')
1918 self.assertEqual(C.reported, 1)
1919 self.assertEqual(len(self.history), 10)
1920 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 1)
James E. Blair7d0dedc2013-02-21 17:26:09 -08001921
James E. Blair18c64442014-03-18 10:14:45 -07001922 def test_noop_job(self):
1923 "Test that the internal noop job works"
1924 A = self.fake_gerrit.addFakeChange('org/noop-project', 'master', 'A')
1925 A.addApproval('CRVW', 2)
1926 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1927 self.waitUntilSettled()
1928
1929 self.assertEqual(len(self.gearman_server.getQueue()), 0)
1930 self.assertTrue(self.sched._areAllBuildsComplete())
1931 self.assertEqual(len(self.history), 0)
1932 self.assertEqual(A.data['status'], 'MERGED')
1933 self.assertEqual(A.reported, 2)
1934
Evgeny Antyshevd6e546c2015-06-11 15:13:57 +00001935 def test_no_job_project(self):
1936 "Test that reports with no jobs don't get sent"
1937 A = self.fake_gerrit.addFakeChange('org/no-jobs-project',
1938 'master', 'A')
1939 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1940 self.waitUntilSettled()
1941
1942 # Change wasn't reported to
1943 self.assertEqual(A.reported, False)
1944
1945 # Check queue is empty afterwards
1946 check_pipeline = self.sched.layout.pipelines['check']
1947 items = check_pipeline.getAllItems()
1948 self.assertEqual(len(items), 0)
1949
1950 self.assertEqual(len(self.history), 0)
1951
James E. Blair7d0dedc2013-02-21 17:26:09 -08001952 def test_zuul_refs(self):
1953 "Test that zuul refs exist and have the right changes"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001954 self.worker.hold_jobs_in_build = True
James E. Blair7d0dedc2013-02-21 17:26:09 -08001955 M1 = self.fake_gerrit.addFakeChange('org/project1', 'master', 'M1')
1956 M1.setMerged()
1957 M2 = self.fake_gerrit.addFakeChange('org/project2', 'master', 'M2')
1958 M2.setMerged()
1959
1960 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
1961 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
1962 C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
1963 D = self.fake_gerrit.addFakeChange('org/project2', 'master', 'D')
1964 A.addApproval('CRVW', 2)
1965 B.addApproval('CRVW', 2)
1966 C.addApproval('CRVW', 2)
1967 D.addApproval('CRVW', 2)
1968 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1969 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1970 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1971 self.fake_gerrit.addEvent(D.addApproval('APRV', 1))
1972
1973 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001974 self.worker.release('.*-merge')
James E. Blair7d0dedc2013-02-21 17:26:09 -08001975 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001976 self.worker.release('.*-merge')
James E. Blair7d0dedc2013-02-21 17:26:09 -08001977 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001978 self.worker.release('.*-merge')
James E. Blair7d0dedc2013-02-21 17:26:09 -08001979 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001980 self.worker.release('.*-merge')
James E. Blair7d0dedc2013-02-21 17:26:09 -08001981 self.waitUntilSettled()
1982
James E. Blair7d0dedc2013-02-21 17:26:09 -08001983 a_zref = b_zref = c_zref = d_zref = None
Monty Taylor6bef8ef2013-06-02 08:17:12 -04001984 for x in self.builds:
James E. Blair7d0dedc2013-02-21 17:26:09 -08001985 if x.parameters['ZUUL_CHANGE'] == '3':
1986 a_zref = x.parameters['ZUUL_REF']
1987 if x.parameters['ZUUL_CHANGE'] == '4':
1988 b_zref = x.parameters['ZUUL_REF']
1989 if x.parameters['ZUUL_CHANGE'] == '5':
1990 c_zref = x.parameters['ZUUL_REF']
1991 if x.parameters['ZUUL_CHANGE'] == '6':
1992 d_zref = x.parameters['ZUUL_REF']
1993
1994 # There are... four... refs.
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001995 self.assertIsNotNone(a_zref)
1996 self.assertIsNotNone(b_zref)
1997 self.assertIsNotNone(c_zref)
1998 self.assertIsNotNone(d_zref)
James E. Blair7d0dedc2013-02-21 17:26:09 -08001999
2000 # And they should all be different
2001 refs = set([a_zref, b_zref, c_zref, d_zref])
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002002 self.assertEqual(len(refs), 4)
James E. Blair7d0dedc2013-02-21 17:26:09 -08002003
2004 # a ref should have a, not b, and should not be in project2
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002005 self.assertTrue(self.ref_has_change(a_zref, A))
2006 self.assertFalse(self.ref_has_change(a_zref, B))
2007 self.assertFalse(self.ref_has_change(a_zref, M2))
James E. Blair7d0dedc2013-02-21 17:26:09 -08002008
2009 # b ref should have a and b, and should not be in project2
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002010 self.assertTrue(self.ref_has_change(b_zref, A))
2011 self.assertTrue(self.ref_has_change(b_zref, B))
2012 self.assertFalse(self.ref_has_change(b_zref, M2))
James E. Blair7d0dedc2013-02-21 17:26:09 -08002013
2014 # c ref should have a and b in 1, c in 2
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002015 self.assertTrue(self.ref_has_change(c_zref, A))
2016 self.assertTrue(self.ref_has_change(c_zref, B))
2017 self.assertTrue(self.ref_has_change(c_zref, C))
2018 self.assertFalse(self.ref_has_change(c_zref, D))
James E. Blair7d0dedc2013-02-21 17:26:09 -08002019
2020 # d ref should have a and b in 1, c and d in 2
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002021 self.assertTrue(self.ref_has_change(d_zref, A))
2022 self.assertTrue(self.ref_has_change(d_zref, B))
2023 self.assertTrue(self.ref_has_change(d_zref, C))
2024 self.assertTrue(self.ref_has_change(d_zref, D))
James E. Blair7d0dedc2013-02-21 17:26:09 -08002025
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002026 self.worker.hold_jobs_in_build = False
2027 self.worker.release()
James E. Blair7d0dedc2013-02-21 17:26:09 -08002028 self.waitUntilSettled()
2029
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002030 self.assertEqual(A.data['status'], 'MERGED')
2031 self.assertEqual(A.reported, 2)
2032 self.assertEqual(B.data['status'], 'MERGED')
2033 self.assertEqual(B.reported, 2)
2034 self.assertEqual(C.data['status'], 'MERGED')
2035 self.assertEqual(C.reported, 2)
2036 self.assertEqual(D.data['status'], 'MERGED')
2037 self.assertEqual(D.reported, 2)
James E. Blair70c71582013-03-06 08:50:50 -08002038
James E. Blair4a28a882013-08-23 15:17:33 -07002039 def test_rerun_on_error(self):
2040 "Test that if a worker fails to run a job, it is run again"
2041 self.worker.hold_jobs_in_build = True
2042 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2043 A.addApproval('CRVW', 2)
2044 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2045 self.waitUntilSettled()
2046
2047 self.builds[0].run_error = True
2048 self.worker.hold_jobs_in_build = False
2049 self.worker.release()
2050 self.waitUntilSettled()
2051 self.assertEqual(self.countJobResults(self.history, 'RUN_ERROR'), 1)
2052 self.assertEqual(self.countJobResults(self.history, 'SUCCESS'), 3)
2053
James E. Blair412e5582013-04-22 15:50:12 -07002054 def test_statsd(self):
2055 "Test each of the statsd methods used in the scheduler"
2056 import extras
2057 statsd = extras.try_import('statsd.statsd')
2058 statsd.incr('test-incr')
2059 statsd.timing('test-timing', 3)
Alex Gaynor813d39b2014-05-17 16:17:16 -07002060 statsd.gauge('test-gauge', 12)
James E. Blair412e5582013-04-22 15:50:12 -07002061 self.assertReportedStat('test-incr', '1|c')
2062 self.assertReportedStat('test-timing', '3|ms')
Alex Gaynor813d39b2014-05-17 16:17:16 -07002063 self.assertReportedStat('test-gauge', '12|g')
James E. Blair412e5582013-04-22 15:50:12 -07002064
James E. Blairdad52252014-02-07 16:59:17 -08002065 def test_stuck_job_cleanup(self):
2066 "Test that pending jobs are cleaned up if removed from layout"
James E. Blair18c64442014-03-18 10:14:45 -07002067 # This job won't be registered at startup because it is not in
2068 # the standard layout, but we need it to already be registerd
2069 # for when we reconfigure, as that is when Zuul will attempt
2070 # to run the new job.
2071 self.worker.registerFunction('build:gate-noop')
James E. Blairdad52252014-02-07 16:59:17 -08002072 self.gearman_server.hold_jobs_in_queue = True
2073 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2074 A.addApproval('CRVW', 2)
2075 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2076 self.waitUntilSettled()
2077 self.assertEqual(len(self.gearman_server.getQueue()), 1)
2078
2079 self.config.set('zuul', 'layout_config',
2080 'tests/fixtures/layout-no-jobs.yaml')
2081 self.sched.reconfigure(self.config)
2082 self.waitUntilSettled()
2083
James E. Blair18c64442014-03-18 10:14:45 -07002084 self.gearman_server.release('gate-noop')
James E. Blairdad52252014-02-07 16:59:17 -08002085 self.waitUntilSettled()
2086 self.assertEqual(len(self.gearman_server.getQueue()), 0)
2087 self.assertTrue(self.sched._areAllBuildsComplete())
2088
2089 self.assertEqual(len(self.history), 1)
James E. Blair18c64442014-03-18 10:14:45 -07002090 self.assertEqual(self.history[0].name, 'gate-noop')
James E. Blairdad52252014-02-07 16:59:17 -08002091 self.assertEqual(self.history[0].result, 'SUCCESS')
2092
James E. Blair879dafb2015-07-17 14:04:49 -07002093 def test_file_head(self):
2094 # This is a regression test for an observed bug. A change
2095 # with a file named "HEAD" in the root directory of the repo
2096 # was processed by a merger. It then was unable to reset the
2097 # repo because of:
2098 # GitCommandError: 'git reset --hard HEAD' returned
2099 # with exit code 128
2100 # stderr: 'fatal: ambiguous argument 'HEAD': both revision
2101 # and filename
2102 # Use '--' to separate filenames from revisions'
2103
2104 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2105 A.addPatchset(['HEAD'])
2106 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2107
2108 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
2109 self.waitUntilSettled()
2110
2111 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2112 self.waitUntilSettled()
2113
2114 self.assertIn('Build succeeded', A.messages[0])
2115 self.assertIn('Build succeeded', B.messages[0])
2116
James E. Blair70c71582013-03-06 08:50:50 -08002117 def test_file_jobs(self):
2118 "Test that file jobs run only when appropriate"
2119 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2120 A.addPatchset(['pip-requires'])
2121 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2122 A.addApproval('CRVW', 2)
2123 B.addApproval('CRVW', 2)
2124 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2125 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2126 self.waitUntilSettled()
2127
Monty Taylor6bef8ef2013-06-02 08:17:12 -04002128 testfile_jobs = [x for x in self.history
James E. Blair70c71582013-03-06 08:50:50 -08002129 if x.name == 'project-testfile']
2130
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002131 self.assertEqual(len(testfile_jobs), 1)
2132 self.assertEqual(testfile_jobs[0].changes, '1,2')
2133 self.assertEqual(A.data['status'], 'MERGED')
2134 self.assertEqual(A.reported, 2)
2135 self.assertEqual(B.data['status'], 'MERGED')
2136 self.assertEqual(B.reported, 2)
James E. Blair3c5e5b52013-04-26 11:17:03 -07002137
Maru Newby3fe5f852015-01-13 04:22:14 +00002138 def _test_skip_if_jobs(self, branch, should_skip):
2139 "Test that jobs with a skip-if filter run only when appropriate"
2140 self.config.set('zuul', 'layout_config',
2141 'tests/fixtures/layout-skip-if.yaml')
2142 self.sched.reconfigure(self.config)
2143 self.registerJobs()
2144
2145 change = self.fake_gerrit.addFakeChange('org/project',
2146 branch,
2147 'test skip-if')
2148 self.fake_gerrit.addEvent(change.getPatchsetCreatedEvent(1))
2149 self.waitUntilSettled()
2150
2151 tested_change_ids = [x.changes[0] for x in self.history
2152 if x.name == 'project-test-skip-if']
2153
2154 if should_skip:
2155 self.assertEqual([], tested_change_ids)
2156 else:
2157 self.assertIn(change.data['number'], tested_change_ids)
2158
2159 def test_skip_if_match_skips_job(self):
2160 self._test_skip_if_jobs(branch='master', should_skip=True)
2161
2162 def test_skip_if_no_match_runs_job(self):
2163 self._test_skip_if_jobs(branch='mp', should_skip=False)
2164
James E. Blair3c5e5b52013-04-26 11:17:03 -07002165 def test_test_config(self):
2166 "Test that we can test the config"
Joshua Hesketh352264b2015-08-11 23:42:08 +10002167 self.sched.testConfig(self.config.get('zuul', 'layout_config'),
2168 self.connections)
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002169
2170 def test_build_description(self):
2171 "Test that build descriptions update"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002172 self.worker.registerFunction('set_description:' +
2173 self.worker.worker_id)
2174
2175 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2176 A.addApproval('CRVW', 2)
2177 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2178 self.waitUntilSettled()
Monty Taylor6bef8ef2013-06-02 08:17:12 -04002179 desc = self.history[0].description
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002180 self.log.debug("Description: %s" % desc)
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002181 self.assertTrue(re.search("Branch.*master", desc))
2182 self.assertTrue(re.search("Pipeline.*gate", desc))
2183 self.assertTrue(re.search("project-merge.*SUCCESS", desc))
2184 self.assertTrue(re.search("project-test1.*SUCCESS", desc))
2185 self.assertTrue(re.search("project-test2.*SUCCESS", desc))
2186 self.assertTrue(re.search("Reported result.*SUCCESS", desc))
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002187
James E. Blairc8a1e052014-02-25 09:29:26 -08002188 def test_queue_names(self):
2189 "Test shared change queue names"
2190 project1 = self.sched.layout.projects['org/project1']
2191 project2 = self.sched.layout.projects['org/project2']
2192 q1 = self.sched.layout.pipelines['gate'].getQueue(project1)
2193 q2 = self.sched.layout.pipelines['gate'].getQueue(project2)
2194 self.assertEqual(q1.name, 'integration')
2195 self.assertEqual(q2.name, 'integration')
2196
2197 self.config.set('zuul', 'layout_config',
2198 'tests/fixtures/layout-bad-queue.yaml')
2199 with testtools.ExpectedException(
2200 Exception, "More than one name assigned to change queue"):
2201 self.sched.reconfigure(self.config)
2202
James E. Blair64ed6f22013-07-10 14:07:23 -07002203 def test_queue_precedence(self):
2204 "Test that queue precedence works"
2205
2206 self.gearman_server.hold_jobs_in_queue = True
James E. Blair8de58bd2013-07-18 16:23:33 -07002207 self.worker.hold_jobs_in_build = True
James E. Blair64ed6f22013-07-10 14:07:23 -07002208 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2209 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2210 A.addApproval('CRVW', 2)
2211 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2212
2213 self.waitUntilSettled()
2214 self.gearman_server.hold_jobs_in_queue = False
2215 self.gearman_server.release()
2216 self.waitUntilSettled()
2217
James E. Blair8de58bd2013-07-18 16:23:33 -07002218 # Run one build at a time to ensure non-race order:
James E. Blairb8c16472015-05-05 14:55:26 -07002219 self.orderedRelease()
James E. Blair8de58bd2013-07-18 16:23:33 -07002220 self.worker.hold_jobs_in_build = False
2221 self.waitUntilSettled()
2222
James E. Blair64ed6f22013-07-10 14:07:23 -07002223 self.log.debug(self.history)
2224 self.assertEqual(self.history[0].pipeline, 'gate')
2225 self.assertEqual(self.history[1].pipeline, 'check')
2226 self.assertEqual(self.history[2].pipeline, 'gate')
2227 self.assertEqual(self.history[3].pipeline, 'gate')
2228 self.assertEqual(self.history[4].pipeline, 'check')
2229 self.assertEqual(self.history[5].pipeline, 'check')
2230
Clark Boylana5edbe42014-06-03 16:39:10 -07002231 def test_json_status(self):
James E. Blair1843a552013-07-03 14:19:52 -07002232 "Test that we can retrieve JSON status info"
2233 self.worker.hold_jobs_in_build = True
2234 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2235 A.addApproval('CRVW', 2)
2236 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2237 self.waitUntilSettled()
2238
2239 port = self.webapp.server.socket.getsockname()[1]
2240
Yuriy Taradaya6d452f2014-04-16 12:36:20 +04002241 req = urllib2.Request("http://localhost:%s/status.json" % port)
Yuriy Taradaya6d452f2014-04-16 12:36:20 +04002242 f = urllib2.urlopen(req)
Clark Boylanaa4f2e72014-06-03 21:22:40 -07002243 headers = f.info()
2244 self.assertIn('Content-Length', headers)
2245 self.assertIn('Content-Type', headers)
2246 self.assertEqual(headers['Content-Type'],
2247 'application/json; charset=UTF-8')
Timo Tijhof0ebd2932015-04-02 12:11:21 +01002248 self.assertIn('Access-Control-Allow-Origin', headers)
2249 self.assertIn('Cache-Control', headers)
Clark Boylanaa4f2e72014-06-03 21:22:40 -07002250 self.assertIn('Last-Modified', headers)
Timo Tijhof0ebd2932015-04-02 12:11:21 +01002251 self.assertIn('Expires', headers)
James E. Blair1843a552013-07-03 14:19:52 -07002252 data = f.read()
2253
2254 self.worker.hold_jobs_in_build = False
2255 self.worker.release()
2256 self.waitUntilSettled()
2257
2258 data = json.loads(data)
2259 status_jobs = set()
2260 for p in data['pipelines']:
2261 for q in p['change_queues']:
James E. Blairbfb8e042014-12-30 17:01:44 -08002262 if p['name'] in ['gate', 'conflict']:
Clark Boylanaf2476f2014-01-23 14:47:36 -08002263 self.assertEqual(q['window'], 20)
2264 else:
2265 self.assertEqual(q['window'], 0)
James E. Blair1843a552013-07-03 14:19:52 -07002266 for head in q['heads']:
2267 for change in head:
Clark Boylanaf2476f2014-01-23 14:47:36 -08002268 self.assertTrue(change['active'])
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002269 self.assertEqual(change['id'], '1,1')
James E. Blair1843a552013-07-03 14:19:52 -07002270 for job in change['jobs']:
2271 status_jobs.add(job['name'])
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002272 self.assertIn('project-merge', status_jobs)
2273 self.assertIn('project-test1', status_jobs)
2274 self.assertIn('project-test2', status_jobs)
James E. Blair1843a552013-07-03 14:19:52 -07002275
James E. Blairc3d428e2013-12-03 15:06:48 -08002276 def test_merging_queues(self):
2277 "Test that transitively-connected change queues are merged"
2278 self.config.set('zuul', 'layout_config',
2279 'tests/fixtures/layout-merge-queues.yaml')
2280 self.sched.reconfigure(self.config)
2281 self.assertEqual(len(self.sched.layout.pipelines['gate'].queues), 1)
2282
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002283 def test_node_label(self):
2284 "Test that a job runs on a specific node label"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002285 self.worker.registerFunction('build:node-project-test1:debian')
2286
2287 A = self.fake_gerrit.addFakeChange('org/node-project', 'master', 'A')
2288 A.addApproval('CRVW', 2)
2289 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2290 self.waitUntilSettled()
James E. Blair4ca985f2013-05-30 12:27:43 -07002291
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002292 self.assertIsNone(self.getJobFromHistory('node-project-merge').node)
2293 self.assertEqual(self.getJobFromHistory('node-project-test1').node,
2294 'debian')
2295 self.assertIsNone(self.getJobFromHistory('node-project-test2').node)
James E. Blaircdccd972013-07-01 12:10:22 -07002296
2297 def test_live_reconfiguration(self):
2298 "Test that live reconfiguration works"
2299 self.worker.hold_jobs_in_build = True
2300 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2301 A.addApproval('CRVW', 2)
2302 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2303 self.waitUntilSettled()
2304
2305 self.sched.reconfigure(self.config)
2306
2307 self.worker.hold_jobs_in_build = False
2308 self.worker.release()
2309 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002310 self.assertEqual(self.getJobFromHistory('project-merge').result,
2311 'SUCCESS')
2312 self.assertEqual(self.getJobFromHistory('project-test1').result,
2313 'SUCCESS')
2314 self.assertEqual(self.getJobFromHistory('project-test2').result,
2315 'SUCCESS')
2316 self.assertEqual(A.data['status'], 'MERGED')
2317 self.assertEqual(A.reported, 2)
James E. Blair287c06d2013-07-24 10:39:30 -07002318
James E. Blair6bc782d2015-07-17 16:20:21 -07002319 def test_live_reconfiguration_merge_conflict(self):
2320 # A real-world bug: a change in a gate queue has a merge
2321 # conflict and a job is added to its project while it's
2322 # sitting in the queue. The job gets added to the change and
2323 # enqueued and the change gets stuck.
2324 self.worker.registerFunction('build:project-test3')
2325 self.worker.hold_jobs_in_build = True
2326
2327 # This change is fine. It's here to stop the queue long
2328 # enough for the next change to be subject to the
2329 # reconfiguration, as well as to provide a conflict for the
2330 # next change. This change will succeed and merge.
2331 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2332 A.addPatchset(['conflict'])
2333 A.addApproval('CRVW', 2)
James E. Blair6bc782d2015-07-17 16:20:21 -07002334
2335 # This change will be in merge conflict. During the
2336 # reconfiguration, we will add a job. We want to make sure
2337 # that doesn't cause it to get stuck.
2338 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2339 B.addPatchset(['conflict'])
2340 B.addApproval('CRVW', 2)
James E. Blair4eb21fa2015-07-27 14:56:47 -07002341
2342 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
James E. Blair6bc782d2015-07-17 16:20:21 -07002343 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2344
2345 self.waitUntilSettled()
2346
2347 # No jobs have run yet
2348 self.assertEqual(A.data['status'], 'NEW')
2349 self.assertEqual(A.reported, 1)
2350 self.assertEqual(B.data['status'], 'NEW')
2351 self.assertEqual(B.reported, 1)
2352 self.assertEqual(len(self.history), 0)
2353
2354 # Add the "project-test3" job.
2355 self.config.set('zuul', 'layout_config',
2356 'tests/fixtures/layout-live-'
2357 'reconfiguration-add-job.yaml')
2358 self.sched.reconfigure(self.config)
2359 self.waitUntilSettled()
2360
2361 self.worker.hold_jobs_in_build = False
2362 self.worker.release()
2363 self.waitUntilSettled()
2364
2365 self.assertEqual(A.data['status'], 'MERGED')
2366 self.assertEqual(A.reported, 2)
2367 self.assertEqual(B.data['status'], 'NEW')
2368 self.assertEqual(B.reported, 2)
2369 self.assertEqual(self.getJobFromHistory('project-merge').result,
2370 'SUCCESS')
2371 self.assertEqual(self.getJobFromHistory('project-test1').result,
2372 'SUCCESS')
2373 self.assertEqual(self.getJobFromHistory('project-test2').result,
2374 'SUCCESS')
2375 self.assertEqual(self.getJobFromHistory('project-test3').result,
2376 'SUCCESS')
2377 self.assertEqual(len(self.history), 4)
2378
James E. Blair400e8fd2015-07-30 17:44:45 -07002379 def test_live_reconfiguration_failed_root(self):
James E. Blair6bc782d2015-07-17 16:20:21 -07002380 # An extrapolation of test_live_reconfiguration_merge_conflict
2381 # that tests a job added to a job tree with a failed root does
2382 # not run.
2383 self.worker.registerFunction('build:project-test3')
2384 self.worker.hold_jobs_in_build = True
2385
2386 # This change is fine. It's here to stop the queue long
2387 # enough for the next change to be subject to the
2388 # reconfiguration. This change will succeed and merge.
2389 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2390 A.addPatchset(['conflict'])
2391 A.addApproval('CRVW', 2)
2392 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2393 self.waitUntilSettled()
2394 self.worker.release('.*-merge')
2395 self.waitUntilSettled()
2396
2397 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2398 self.worker.addFailTest('project-merge', B)
2399 B.addApproval('CRVW', 2)
2400 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2401 self.waitUntilSettled()
2402
2403 self.worker.release('.*-merge')
2404 self.waitUntilSettled()
2405
2406 # Both -merge jobs have run, but no others.
2407 self.assertEqual(A.data['status'], 'NEW')
2408 self.assertEqual(A.reported, 1)
2409 self.assertEqual(B.data['status'], 'NEW')
2410 self.assertEqual(B.reported, 1)
2411 self.assertEqual(self.history[0].result, 'SUCCESS')
2412 self.assertEqual(self.history[0].name, 'project-merge')
2413 self.assertEqual(self.history[1].result, 'FAILURE')
2414 self.assertEqual(self.history[1].name, 'project-merge')
2415 self.assertEqual(len(self.history), 2)
2416
2417 # Add the "project-test3" job.
2418 self.config.set('zuul', 'layout_config',
2419 'tests/fixtures/layout-live-'
2420 'reconfiguration-add-job.yaml')
2421 self.sched.reconfigure(self.config)
2422 self.waitUntilSettled()
2423
2424 self.worker.hold_jobs_in_build = False
2425 self.worker.release()
2426 self.waitUntilSettled()
2427
2428 self.assertEqual(A.data['status'], 'MERGED')
2429 self.assertEqual(A.reported, 2)
2430 self.assertEqual(B.data['status'], 'NEW')
2431 self.assertEqual(B.reported, 2)
2432 self.assertEqual(self.history[0].result, 'SUCCESS')
2433 self.assertEqual(self.history[0].name, 'project-merge')
2434 self.assertEqual(self.history[1].result, 'FAILURE')
2435 self.assertEqual(self.history[1].name, 'project-merge')
2436 self.assertEqual(self.history[2].result, 'SUCCESS')
2437 self.assertEqual(self.history[3].result, 'SUCCESS')
2438 self.assertEqual(self.history[4].result, 'SUCCESS')
2439 self.assertEqual(len(self.history), 5)
2440
James E. Blair400e8fd2015-07-30 17:44:45 -07002441 def test_live_reconfiguration_failed_job(self):
2442 # Test that a change with a removed failing job does not
2443 # disrupt reconfiguration. If a change has a failed job and
2444 # that job is removed during a reconfiguration, we observed a
2445 # bug where the code to re-set build statuses would run on
2446 # that build and raise an exception because the job no longer
2447 # existed.
2448 self.worker.hold_jobs_in_build = True
2449
2450 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2451
2452 # This change will fail and later be removed by the reconfiguration.
2453 self.worker.addFailTest('project-test1', A)
2454
2455 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2456 self.waitUntilSettled()
2457 self.worker.release('.*-merge')
2458 self.waitUntilSettled()
2459 self.worker.release('project-test1')
2460 self.waitUntilSettled()
2461
2462 self.assertEqual(A.data['status'], 'NEW')
2463 self.assertEqual(A.reported, 0)
2464
2465 self.assertEqual(self.getJobFromHistory('project-merge').result,
2466 'SUCCESS')
2467 self.assertEqual(self.getJobFromHistory('project-test1').result,
2468 'FAILURE')
2469 self.assertEqual(len(self.history), 2)
2470
2471 # Remove the test1 job.
2472 self.config.set('zuul', 'layout_config',
2473 'tests/fixtures/layout-live-'
2474 'reconfiguration-failed-job.yaml')
2475 self.sched.reconfigure(self.config)
2476 self.waitUntilSettled()
2477
2478 self.worker.hold_jobs_in_build = False
2479 self.worker.release()
2480 self.waitUntilSettled()
2481
2482 self.assertEqual(self.getJobFromHistory('project-test2').result,
2483 'SUCCESS')
2484 self.assertEqual(self.getJobFromHistory('project-testfile').result,
2485 'SUCCESS')
2486 self.assertEqual(len(self.history), 4)
2487
2488 self.assertEqual(A.data['status'], 'NEW')
2489 self.assertEqual(A.reported, 1)
2490 self.assertIn('Build succeeded', A.messages[0])
2491 # Ensure the removed job was not included in the report.
2492 self.assertNotIn('project-test1', A.messages[0])
2493
James E. Blairfe707d12015-08-05 15:18:15 -07002494 def test_live_reconfiguration_shared_queue(self):
2495 # Test that a change with a failing job which was removed from
2496 # this project but otherwise still exists in the system does
2497 # not disrupt reconfiguration.
2498
2499 self.worker.hold_jobs_in_build = True
2500
2501 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
2502
2503 self.worker.addFailTest('project1-project2-integration', A)
2504
2505 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2506 self.waitUntilSettled()
2507 self.worker.release('.*-merge')
2508 self.waitUntilSettled()
2509 self.worker.release('project1-project2-integration')
2510 self.waitUntilSettled()
2511
2512 self.assertEqual(A.data['status'], 'NEW')
2513 self.assertEqual(A.reported, 0)
2514
2515 self.assertEqual(self.getJobFromHistory('project1-merge').result,
2516 'SUCCESS')
2517 self.assertEqual(self.getJobFromHistory(
2518 'project1-project2-integration').result, 'FAILURE')
2519 self.assertEqual(len(self.history), 2)
2520
2521 # Remove the integration job.
2522 self.config.set('zuul', 'layout_config',
2523 'tests/fixtures/layout-live-'
2524 'reconfiguration-shared-queue.yaml')
2525 self.sched.reconfigure(self.config)
2526 self.waitUntilSettled()
2527
2528 self.worker.hold_jobs_in_build = False
2529 self.worker.release()
2530 self.waitUntilSettled()
2531
2532 self.assertEqual(self.getJobFromHistory('project1-merge').result,
2533 'SUCCESS')
2534 self.assertEqual(self.getJobFromHistory('project1-test1').result,
2535 'SUCCESS')
2536 self.assertEqual(self.getJobFromHistory('project1-test2').result,
2537 'SUCCESS')
2538 self.assertEqual(self.getJobFromHistory(
2539 'project1-project2-integration').result, 'FAILURE')
2540 self.assertEqual(len(self.history), 4)
2541
2542 self.assertEqual(A.data['status'], 'NEW')
2543 self.assertEqual(A.reported, 1)
2544 self.assertIn('Build succeeded', A.messages[0])
2545 # Ensure the removed job was not included in the report.
2546 self.assertNotIn('project1-project2-integration', A.messages[0])
2547
Evgeny Antyshev0deaaad2015-08-03 20:22:56 +00002548 def test_live_reconfiguration_del_project(self):
2549 # Test project deletion from layout
2550 # while changes are enqueued
2551
2552 self.worker.hold_jobs_in_build = True
2553 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2554 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
2555 C = self.fake_gerrit.addFakeChange('org/project1', 'master', 'C')
2556
2557 # A Depends-On: B
2558 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
2559 A.subject, B.data['id'])
2560 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2561
2562 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2563 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
2564 self.waitUntilSettled()
2565 self.worker.release('.*-merge')
2566 self.waitUntilSettled()
2567 self.assertEqual(len(self.builds), 5)
2568
2569 # This layout defines only org/project, not org/project1
2570 self.config.set('zuul', 'layout_config',
2571 'tests/fixtures/layout-live-'
2572 'reconfiguration-del-project.yaml')
2573 self.sched.reconfigure(self.config)
2574 self.waitUntilSettled()
2575
2576 # Builds for C aborted, builds for A succeed,
2577 # and have change B applied ahead
2578 job_c = self.getJobFromHistory('project1-test1')
2579 self.assertEqual(job_c.changes, '3,1')
2580 self.assertEqual(job_c.result, 'ABORTED')
2581
2582 self.worker.hold_jobs_in_build = False
2583 self.worker.release()
2584 self.waitUntilSettled()
2585
2586 self.assertEqual(self.getJobFromHistory('project-test1').changes,
2587 '2,1 1,1')
2588
2589 self.assertEqual(A.data['status'], 'NEW')
2590 self.assertEqual(B.data['status'], 'NEW')
2591 self.assertEqual(C.data['status'], 'NEW')
2592 self.assertEqual(A.reported, 1)
2593 self.assertEqual(B.reported, 0)
2594 self.assertEqual(C.reported, 0)
2595
2596 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 0)
2597 self.assertIn('Build succeeded', A.messages[0])
2598
James E. Blaire712d9f2013-07-31 11:40:11 -07002599 def test_live_reconfiguration_functions(self):
2600 "Test live reconfiguration with a custom function"
2601 self.worker.registerFunction('build:node-project-test1:debian')
2602 self.worker.registerFunction('build:node-project-test1:wheezy')
2603 A = self.fake_gerrit.addFakeChange('org/node-project', 'master', 'A')
2604 A.addApproval('CRVW', 2)
2605 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2606 self.waitUntilSettled()
2607
2608 self.assertIsNone(self.getJobFromHistory('node-project-merge').node)
2609 self.assertEqual(self.getJobFromHistory('node-project-test1').node,
2610 'debian')
2611 self.assertIsNone(self.getJobFromHistory('node-project-test2').node)
2612
2613 self.config.set('zuul', 'layout_config',
2614 'tests/fixtures/layout-live-'
2615 'reconfiguration-functions.yaml')
2616 self.sched.reconfigure(self.config)
2617 self.worker.build_history = []
2618
2619 B = self.fake_gerrit.addFakeChange('org/node-project', 'master', 'B')
2620 B.addApproval('CRVW', 2)
2621 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2622 self.waitUntilSettled()
2623
2624 self.assertIsNone(self.getJobFromHistory('node-project-merge').node)
2625 self.assertEqual(self.getJobFromHistory('node-project-test1').node,
2626 'wheezy')
2627 self.assertIsNone(self.getJobFromHistory('node-project-test2').node)
2628
James E. Blair287c06d2013-07-24 10:39:30 -07002629 def test_delayed_repo_init(self):
2630 self.config.set('zuul', 'layout_config',
2631 'tests/fixtures/layout-delayed-repo-init.yaml')
2632 self.sched.reconfigure(self.config)
2633
2634 self.init_repo("org/new-project")
2635 A = self.fake_gerrit.addFakeChange('org/new-project', 'master', 'A')
2636
2637 A.addApproval('CRVW', 2)
2638 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2639 self.waitUntilSettled()
2640 self.assertEqual(self.getJobFromHistory('project-merge').result,
2641 'SUCCESS')
2642 self.assertEqual(self.getJobFromHistory('project-test1').result,
2643 'SUCCESS')
2644 self.assertEqual(self.getJobFromHistory('project-test2').result,
2645 'SUCCESS')
2646 self.assertEqual(A.data['status'], 'MERGED')
2647 self.assertEqual(A.reported, 2)
James E. Blair63bb0ef2013-07-29 17:14:51 -07002648
Clark Boylan6dbbc482013-10-18 10:57:31 -07002649 def test_repo_deleted(self):
2650 self.config.set('zuul', 'layout_config',
2651 'tests/fixtures/layout-repo-deleted.yaml')
2652 self.sched.reconfigure(self.config)
2653
2654 self.init_repo("org/delete-project")
2655 A = self.fake_gerrit.addFakeChange('org/delete-project', 'master', 'A')
2656
2657 A.addApproval('CRVW', 2)
2658 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2659 self.waitUntilSettled()
2660 self.assertEqual(self.getJobFromHistory('project-merge').result,
2661 'SUCCESS')
2662 self.assertEqual(self.getJobFromHistory('project-test1').result,
2663 'SUCCESS')
2664 self.assertEqual(self.getJobFromHistory('project-test2').result,
2665 'SUCCESS')
2666 self.assertEqual(A.data['status'], 'MERGED')
2667 self.assertEqual(A.reported, 2)
2668
2669 # Delete org/new-project zuul repo. Should be recloned.
2670 shutil.rmtree(os.path.join(self.git_root, "org/delete-project"))
2671
2672 B = self.fake_gerrit.addFakeChange('org/delete-project', 'master', 'B')
2673
2674 B.addApproval('CRVW', 2)
2675 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2676 self.waitUntilSettled()
2677 self.assertEqual(self.getJobFromHistory('project-merge').result,
2678 'SUCCESS')
2679 self.assertEqual(self.getJobFromHistory('project-test1').result,
2680 'SUCCESS')
2681 self.assertEqual(self.getJobFromHistory('project-test2').result,
2682 'SUCCESS')
2683 self.assertEqual(B.data['status'], 'MERGED')
2684 self.assertEqual(B.reported, 2)
2685
James E. Blair63bb0ef2013-07-29 17:14:51 -07002686 def test_timer(self):
2687 "Test that a periodic job is triggered"
2688 self.worker.hold_jobs_in_build = True
2689 self.config.set('zuul', 'layout_config',
2690 'tests/fixtures/layout-timer.yaml')
2691 self.sched.reconfigure(self.config)
2692 self.registerJobs()
2693
Clark Boylan3ee090a2014-04-03 20:55:09 -07002694 # The pipeline triggers every second, so we should have seen
2695 # several by now.
2696 time.sleep(5)
James E. Blair63bb0ef2013-07-29 17:14:51 -07002697 self.waitUntilSettled()
Clark Boylan3ee090a2014-04-03 20:55:09 -07002698
2699 self.assertEqual(len(self.builds), 2)
2700
James E. Blair63bb0ef2013-07-29 17:14:51 -07002701 port = self.webapp.server.socket.getsockname()[1]
2702
2703 f = urllib.urlopen("http://localhost:%s/status.json" % port)
2704 data = f.read()
2705
2706 self.worker.hold_jobs_in_build = False
Clark Boylan3ee090a2014-04-03 20:55:09 -07002707 # Stop queuing timer triggered jobs so that the assertions
2708 # below don't race against more jobs being queued.
2709 self.config.set('zuul', 'layout_config',
2710 'tests/fixtures/layout-no-timer.yaml')
2711 self.sched.reconfigure(self.config)
2712 self.registerJobs()
James E. Blair63bb0ef2013-07-29 17:14:51 -07002713 self.worker.release()
2714 self.waitUntilSettled()
2715
2716 self.assertEqual(self.getJobFromHistory(
2717 'project-bitrot-stable-old').result, 'SUCCESS')
2718 self.assertEqual(self.getJobFromHistory(
2719 'project-bitrot-stable-older').result, 'SUCCESS')
2720
2721 data = json.loads(data)
2722 status_jobs = set()
2723 for p in data['pipelines']:
2724 for q in p['change_queues']:
2725 for head in q['heads']:
2726 for change in head:
Alex Gaynorddb9ef32013-09-16 21:04:58 -07002727 self.assertEqual(change['id'], None)
James E. Blair63bb0ef2013-07-29 17:14:51 -07002728 for job in change['jobs']:
2729 status_jobs.add(job['name'])
2730 self.assertIn('project-bitrot-stable-old', status_jobs)
2731 self.assertIn('project-bitrot-stable-older', status_jobs)
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002732
James E. Blair4f6033c2014-03-27 15:49:09 -07002733 def test_idle(self):
2734 "Test that frequent periodic jobs work"
2735 self.worker.hold_jobs_in_build = True
James E. Blair4f6033c2014-03-27 15:49:09 -07002736
Clark Boylan3ee090a2014-04-03 20:55:09 -07002737 for x in range(1, 3):
2738 # Test that timer triggers periodic jobs even across
2739 # layout config reloads.
2740 # Start timer trigger
2741 self.config.set('zuul', 'layout_config',
2742 'tests/fixtures/layout-idle.yaml')
2743 self.sched.reconfigure(self.config)
2744 self.registerJobs()
James E. Blair995fc0f2016-02-04 16:48:31 -08002745 self.waitUntilSettled()
James E. Blair4f6033c2014-03-27 15:49:09 -07002746
Clark Boylan3ee090a2014-04-03 20:55:09 -07002747 # The pipeline triggers every second, so we should have seen
2748 # several by now.
2749 time.sleep(5)
Clark Boylan3ee090a2014-04-03 20:55:09 -07002750
2751 # Stop queuing timer triggered jobs so that the assertions
2752 # below don't race against more jobs being queued.
2753 self.config.set('zuul', 'layout_config',
2754 'tests/fixtures/layout-no-timer.yaml')
2755 self.sched.reconfigure(self.config)
2756 self.registerJobs()
James E. Blair995fc0f2016-02-04 16:48:31 -08002757 self.waitUntilSettled()
Clark Boylan3ee090a2014-04-03 20:55:09 -07002758
2759 self.assertEqual(len(self.builds), 2)
2760 self.worker.release('.*')
2761 self.waitUntilSettled()
2762 self.assertEqual(len(self.builds), 0)
2763 self.assertEqual(len(self.history), x * 2)
James E. Blair4f6033c2014-03-27 15:49:09 -07002764
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002765 def test_check_smtp_pool(self):
2766 self.config.set('zuul', 'layout_config',
2767 'tests/fixtures/layout-smtp.yaml')
2768 self.sched.reconfigure(self.config)
2769
2770 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2771 self.waitUntilSettled()
2772
2773 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2774 self.waitUntilSettled()
2775
James E. Blairff80a2f2013-12-27 13:24:06 -08002776 self.assertEqual(len(self.smtp_messages), 2)
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002777
2778 # A.messages only holds what FakeGerrit places in it. Thus we
2779 # work on the knowledge of what the first message should be as
2780 # it is only configured to go to SMTP.
2781
2782 self.assertEqual('zuul@example.com',
James E. Blairff80a2f2013-12-27 13:24:06 -08002783 self.smtp_messages[0]['from_email'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002784 self.assertEqual(['you@example.com'],
James E. Blairff80a2f2013-12-27 13:24:06 -08002785 self.smtp_messages[0]['to_email'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002786 self.assertEqual('Starting check jobs.',
James E. Blairff80a2f2013-12-27 13:24:06 -08002787 self.smtp_messages[0]['body'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002788
2789 self.assertEqual('zuul_from@example.com',
James E. Blairff80a2f2013-12-27 13:24:06 -08002790 self.smtp_messages[1]['from_email'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002791 self.assertEqual(['alternative_me@example.com'],
James E. Blairff80a2f2013-12-27 13:24:06 -08002792 self.smtp_messages[1]['to_email'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002793 self.assertEqual(A.messages[0],
James E. Blairff80a2f2013-12-27 13:24:06 -08002794 self.smtp_messages[1]['body'])
James E. Blairad28e912013-11-27 10:43:22 -08002795
James E. Blaire5910202013-12-27 09:50:31 -08002796 def test_timer_smtp(self):
2797 "Test that a periodic job is triggered"
Clark Boylan3ee090a2014-04-03 20:55:09 -07002798 self.worker.hold_jobs_in_build = True
James E. Blaire5910202013-12-27 09:50:31 -08002799 self.config.set('zuul', 'layout_config',
2800 'tests/fixtures/layout-timer-smtp.yaml')
2801 self.sched.reconfigure(self.config)
2802 self.registerJobs()
2803
Clark Boylan3ee090a2014-04-03 20:55:09 -07002804 # The pipeline triggers every second, so we should have seen
2805 # several by now.
2806 time.sleep(5)
James E. Blaire5910202013-12-27 09:50:31 -08002807 self.waitUntilSettled()
2808
Clark Boylan3ee090a2014-04-03 20:55:09 -07002809 self.assertEqual(len(self.builds), 2)
2810 self.worker.release('.*')
2811 self.waitUntilSettled()
2812 self.assertEqual(len(self.history), 2)
2813
James E. Blaire5910202013-12-27 09:50:31 -08002814 self.assertEqual(self.getJobFromHistory(
2815 'project-bitrot-stable-old').result, 'SUCCESS')
2816 self.assertEqual(self.getJobFromHistory(
2817 'project-bitrot-stable-older').result, 'SUCCESS')
2818
James E. Blairff80a2f2013-12-27 13:24:06 -08002819 self.assertEqual(len(self.smtp_messages), 1)
James E. Blaire5910202013-12-27 09:50:31 -08002820
2821 # A.messages only holds what FakeGerrit places in it. Thus we
2822 # work on the knowledge of what the first message should be as
2823 # it is only configured to go to SMTP.
2824
2825 self.assertEqual('zuul_from@example.com',
James E. Blairff80a2f2013-12-27 13:24:06 -08002826 self.smtp_messages[0]['from_email'])
James E. Blaire5910202013-12-27 09:50:31 -08002827 self.assertEqual(['alternative_me@example.com'],
James E. Blairff80a2f2013-12-27 13:24:06 -08002828 self.smtp_messages[0]['to_email'])
James E. Blaire5910202013-12-27 09:50:31 -08002829 self.assertIn('Subject: Periodic check for org/project succeeded',
James E. Blairff80a2f2013-12-27 13:24:06 -08002830 self.smtp_messages[0]['headers'])
James E. Blaire5910202013-12-27 09:50:31 -08002831
Clark Boylan3ee090a2014-04-03 20:55:09 -07002832 # Stop queuing timer triggered jobs and let any that may have
2833 # queued through so that end of test assertions pass.
2834 self.config.set('zuul', 'layout_config',
2835 'tests/fixtures/layout-no-timer.yaml')
2836 self.sched.reconfigure(self.config)
2837 self.registerJobs()
James E. Blairf8058972014-08-15 16:09:16 -07002838 self.waitUntilSettled()
Clark Boylan3ee090a2014-04-03 20:55:09 -07002839 self.worker.release('.*')
2840 self.waitUntilSettled()
2841
James E. Blair91e34592015-07-31 16:45:59 -07002842 def test_client_enqueue_change(self):
James E. Blairad28e912013-11-27 10:43:22 -08002843 "Test that the RPC client can enqueue a change"
2844 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2845 A.addApproval('CRVW', 2)
2846 A.addApproval('APRV', 1)
2847
2848 client = zuul.rpcclient.RPCClient('127.0.0.1',
2849 self.gearman_server.port)
2850 r = client.enqueue(pipeline='gate',
2851 project='org/project',
2852 trigger='gerrit',
James E. Blair36658cf2013-12-06 17:53:48 -08002853 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08002854 self.waitUntilSettled()
2855 self.assertEqual(self.getJobFromHistory('project-merge').result,
2856 'SUCCESS')
2857 self.assertEqual(self.getJobFromHistory('project-test1').result,
2858 'SUCCESS')
2859 self.assertEqual(self.getJobFromHistory('project-test2').result,
2860 'SUCCESS')
2861 self.assertEqual(A.data['status'], 'MERGED')
2862 self.assertEqual(A.reported, 2)
2863 self.assertEqual(r, True)
2864
James E. Blair91e34592015-07-31 16:45:59 -07002865 def test_client_enqueue_ref(self):
2866 "Test that the RPC client can enqueue a ref"
2867
2868 client = zuul.rpcclient.RPCClient('127.0.0.1',
2869 self.gearman_server.port)
2870 r = client.enqueue_ref(
2871 pipeline='post',
2872 project='org/project',
2873 trigger='gerrit',
2874 ref='master',
2875 oldrev='90f173846e3af9154517b88543ffbd1691f31366',
2876 newrev='d479a0bfcb34da57a31adb2a595c0cf687812543')
2877 self.waitUntilSettled()
2878 job_names = [x.name for x in self.history]
2879 self.assertEqual(len(self.history), 1)
2880 self.assertIn('project-post', job_names)
2881 self.assertEqual(r, True)
2882
James E. Blairad28e912013-11-27 10:43:22 -08002883 def test_client_enqueue_negative(self):
2884 "Test that the RPC client returns errors"
2885 client = zuul.rpcclient.RPCClient('127.0.0.1',
2886 self.gearman_server.port)
2887 with testtools.ExpectedException(zuul.rpcclient.RPCFailure,
2888 "Invalid project"):
2889 r = client.enqueue(pipeline='gate',
2890 project='project-does-not-exist',
2891 trigger='gerrit',
James E. Blair36658cf2013-12-06 17:53:48 -08002892 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08002893 client.shutdown()
2894 self.assertEqual(r, False)
2895
2896 with testtools.ExpectedException(zuul.rpcclient.RPCFailure,
2897 "Invalid pipeline"):
2898 r = client.enqueue(pipeline='pipeline-does-not-exist',
2899 project='org/project',
2900 trigger='gerrit',
James E. Blair36658cf2013-12-06 17:53:48 -08002901 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08002902 client.shutdown()
2903 self.assertEqual(r, False)
2904
2905 with testtools.ExpectedException(zuul.rpcclient.RPCFailure,
2906 "Invalid trigger"):
2907 r = client.enqueue(pipeline='gate',
2908 project='org/project',
2909 trigger='trigger-does-not-exist',
James E. Blair36658cf2013-12-06 17:53:48 -08002910 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08002911 client.shutdown()
2912 self.assertEqual(r, False)
2913
2914 with testtools.ExpectedException(zuul.rpcclient.RPCFailure,
2915 "Invalid change"):
2916 r = client.enqueue(pipeline='gate',
2917 project='org/project',
2918 trigger='gerrit',
James E. Blair36658cf2013-12-06 17:53:48 -08002919 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08002920 client.shutdown()
2921 self.assertEqual(r, False)
2922
2923 self.waitUntilSettled()
2924 self.assertEqual(len(self.history), 0)
2925 self.assertEqual(len(self.builds), 0)
James E. Blair36658cf2013-12-06 17:53:48 -08002926
2927 def test_client_promote(self):
2928 "Test that the RPC client can promote a change"
2929 self.worker.hold_jobs_in_build = True
2930 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2931 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2932 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
2933 A.addApproval('CRVW', 2)
2934 B.addApproval('CRVW', 2)
2935 C.addApproval('CRVW', 2)
2936
2937 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2938 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2939 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
2940
2941 self.waitUntilSettled()
2942
Sean Daguef39b9ca2014-01-10 21:34:35 -05002943 items = self.sched.layout.pipelines['gate'].getAllItems()
2944 enqueue_times = {}
2945 for item in items:
2946 enqueue_times[str(item.change)] = item.enqueue_time
2947
James E. Blair36658cf2013-12-06 17:53:48 -08002948 client = zuul.rpcclient.RPCClient('127.0.0.1',
2949 self.gearman_server.port)
2950 r = client.promote(pipeline='gate',
2951 change_ids=['2,1', '3,1'])
2952
Sean Daguef39b9ca2014-01-10 21:34:35 -05002953 # ensure that enqueue times are durable
2954 items = self.sched.layout.pipelines['gate'].getAllItems()
2955 for item in items:
2956 self.assertEqual(
2957 enqueue_times[str(item.change)], item.enqueue_time)
2958
James E. Blair78acec92014-02-06 07:11:32 -08002959 self.waitUntilSettled()
James E. Blair36658cf2013-12-06 17:53:48 -08002960 self.worker.release('.*-merge')
2961 self.waitUntilSettled()
2962 self.worker.release('.*-merge')
2963 self.waitUntilSettled()
2964 self.worker.release('.*-merge')
2965 self.waitUntilSettled()
2966
2967 self.assertEqual(len(self.builds), 6)
2968 self.assertEqual(self.builds[0].name, 'project-test1')
2969 self.assertEqual(self.builds[1].name, 'project-test2')
2970 self.assertEqual(self.builds[2].name, 'project-test1')
2971 self.assertEqual(self.builds[3].name, 'project-test2')
2972 self.assertEqual(self.builds[4].name, 'project-test1')
2973 self.assertEqual(self.builds[5].name, 'project-test2')
2974
2975 self.assertTrue(self.job_has_changes(self.builds[0], B))
2976 self.assertFalse(self.job_has_changes(self.builds[0], A))
2977 self.assertFalse(self.job_has_changes(self.builds[0], C))
2978
2979 self.assertTrue(self.job_has_changes(self.builds[2], B))
2980 self.assertTrue(self.job_has_changes(self.builds[2], C))
2981 self.assertFalse(self.job_has_changes(self.builds[2], A))
2982
2983 self.assertTrue(self.job_has_changes(self.builds[4], B))
2984 self.assertTrue(self.job_has_changes(self.builds[4], C))
2985 self.assertTrue(self.job_has_changes(self.builds[4], A))
2986
2987 self.worker.release()
2988 self.waitUntilSettled()
2989
2990 self.assertEqual(A.data['status'], 'MERGED')
2991 self.assertEqual(A.reported, 2)
2992 self.assertEqual(B.data['status'], 'MERGED')
2993 self.assertEqual(B.reported, 2)
2994 self.assertEqual(C.data['status'], 'MERGED')
2995 self.assertEqual(C.reported, 2)
2996
2997 client.shutdown()
2998 self.assertEqual(r, True)
2999
3000 def test_client_promote_dependent(self):
3001 "Test that the RPC client can promote a dependent change"
3002 # C (depends on B) -> B -> A ; then promote C to get:
3003 # A -> C (depends on B) -> B
3004 self.worker.hold_jobs_in_build = True
3005 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3006 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
3007 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
3008
3009 C.setDependsOn(B, 1)
3010
3011 A.addApproval('CRVW', 2)
3012 B.addApproval('CRVW', 2)
3013 C.addApproval('CRVW', 2)
3014
3015 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3016 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3017 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
3018
3019 self.waitUntilSettled()
3020
3021 client = zuul.rpcclient.RPCClient('127.0.0.1',
3022 self.gearman_server.port)
3023 r = client.promote(pipeline='gate',
3024 change_ids=['3,1'])
3025
James E. Blair78acec92014-02-06 07:11:32 -08003026 self.waitUntilSettled()
James E. Blair36658cf2013-12-06 17:53:48 -08003027 self.worker.release('.*-merge')
3028 self.waitUntilSettled()
3029 self.worker.release('.*-merge')
3030 self.waitUntilSettled()
3031 self.worker.release('.*-merge')
3032 self.waitUntilSettled()
3033
3034 self.assertEqual(len(self.builds), 6)
3035 self.assertEqual(self.builds[0].name, 'project-test1')
3036 self.assertEqual(self.builds[1].name, 'project-test2')
3037 self.assertEqual(self.builds[2].name, 'project-test1')
3038 self.assertEqual(self.builds[3].name, 'project-test2')
3039 self.assertEqual(self.builds[4].name, 'project-test1')
3040 self.assertEqual(self.builds[5].name, 'project-test2')
3041
3042 self.assertTrue(self.job_has_changes(self.builds[0], B))
3043 self.assertFalse(self.job_has_changes(self.builds[0], A))
3044 self.assertFalse(self.job_has_changes(self.builds[0], C))
3045
3046 self.assertTrue(self.job_has_changes(self.builds[2], B))
3047 self.assertTrue(self.job_has_changes(self.builds[2], C))
3048 self.assertFalse(self.job_has_changes(self.builds[2], A))
3049
3050 self.assertTrue(self.job_has_changes(self.builds[4], B))
3051 self.assertTrue(self.job_has_changes(self.builds[4], C))
3052 self.assertTrue(self.job_has_changes(self.builds[4], A))
3053
3054 self.worker.release()
3055 self.waitUntilSettled()
3056
3057 self.assertEqual(A.data['status'], 'MERGED')
3058 self.assertEqual(A.reported, 2)
3059 self.assertEqual(B.data['status'], 'MERGED')
3060 self.assertEqual(B.reported, 2)
3061 self.assertEqual(C.data['status'], 'MERGED')
3062 self.assertEqual(C.reported, 2)
3063
3064 client.shutdown()
3065 self.assertEqual(r, True)
3066
3067 def test_client_promote_negative(self):
3068 "Test that the RPC client returns errors for promotion"
3069 self.worker.hold_jobs_in_build = True
3070 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3071 A.addApproval('CRVW', 2)
3072 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3073 self.waitUntilSettled()
3074
3075 client = zuul.rpcclient.RPCClient('127.0.0.1',
3076 self.gearman_server.port)
3077
3078 with testtools.ExpectedException(zuul.rpcclient.RPCFailure):
3079 r = client.promote(pipeline='nonexistent',
3080 change_ids=['2,1', '3,1'])
3081 client.shutdown()
3082 self.assertEqual(r, False)
3083
3084 with testtools.ExpectedException(zuul.rpcclient.RPCFailure):
3085 r = client.promote(pipeline='gate',
3086 change_ids=['4,1'])
3087 client.shutdown()
3088 self.assertEqual(r, False)
3089
3090 self.worker.hold_jobs_in_build = False
3091 self.worker.release()
3092 self.waitUntilSettled()
Clark Boylan7603a372014-01-21 11:43:20 -08003093
3094 def test_queue_rate_limiting(self):
3095 "Test that DependentPipelines are rate limited with dep across window"
3096 self.config.set('zuul', 'layout_config',
3097 'tests/fixtures/layout-rate-limit.yaml')
3098 self.sched.reconfigure(self.config)
3099 self.worker.hold_jobs_in_build = True
3100 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3101 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
3102 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
3103
3104 C.setDependsOn(B, 1)
3105 self.worker.addFailTest('project-test1', A)
3106
3107 A.addApproval('CRVW', 2)
3108 B.addApproval('CRVW', 2)
3109 C.addApproval('CRVW', 2)
3110
3111 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3112 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3113 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
3114 self.waitUntilSettled()
3115
3116 # Only A and B will have their merge jobs queued because
3117 # window is 2.
3118 self.assertEqual(len(self.builds), 2)
3119 self.assertEqual(self.builds[0].name, 'project-merge')
3120 self.assertEqual(self.builds[1].name, 'project-merge')
3121
3122 self.worker.release('.*-merge')
3123 self.waitUntilSettled()
3124 self.worker.release('.*-merge')
3125 self.waitUntilSettled()
3126
3127 # Only A and B will have their test jobs queued because
3128 # window is 2.
3129 self.assertEqual(len(self.builds), 4)
3130 self.assertEqual(self.builds[0].name, 'project-test1')
3131 self.assertEqual(self.builds[1].name, 'project-test2')
3132 self.assertEqual(self.builds[2].name, 'project-test1')
3133 self.assertEqual(self.builds[3].name, 'project-test2')
3134
3135 self.worker.release('project-.*')
3136 self.waitUntilSettled()
3137
3138 queue = self.sched.layout.pipelines['gate'].queues[0]
3139 # A failed so window is reduced by 1 to 1.
3140 self.assertEqual(queue.window, 1)
3141 self.assertEqual(queue.window_floor, 1)
3142 self.assertEqual(A.data['status'], 'NEW')
3143
3144 # Gate is reset and only B's merge job is queued because
3145 # window shrunk to 1.
3146 self.assertEqual(len(self.builds), 1)
3147 self.assertEqual(self.builds[0].name, 'project-merge')
3148
3149 self.worker.release('.*-merge')
3150 self.waitUntilSettled()
3151
3152 # Only B's test jobs are queued because window is still 1.
3153 self.assertEqual(len(self.builds), 2)
3154 self.assertEqual(self.builds[0].name, 'project-test1')
3155 self.assertEqual(self.builds[1].name, 'project-test2')
3156
3157 self.worker.release('project-.*')
3158 self.waitUntilSettled()
3159
3160 # B was successfully merged so window is increased to 2.
3161 self.assertEqual(queue.window, 2)
3162 self.assertEqual(queue.window_floor, 1)
3163 self.assertEqual(B.data['status'], 'MERGED')
3164
3165 # Only C is left and its merge job is queued.
3166 self.assertEqual(len(self.builds), 1)
3167 self.assertEqual(self.builds[0].name, 'project-merge')
3168
3169 self.worker.release('.*-merge')
3170 self.waitUntilSettled()
3171
3172 # After successful merge job the test jobs for C are queued.
3173 self.assertEqual(len(self.builds), 2)
3174 self.assertEqual(self.builds[0].name, 'project-test1')
3175 self.assertEqual(self.builds[1].name, 'project-test2')
3176
3177 self.worker.release('project-.*')
3178 self.waitUntilSettled()
3179
3180 # C successfully merged so window is bumped to 3.
3181 self.assertEqual(queue.window, 3)
3182 self.assertEqual(queue.window_floor, 1)
3183 self.assertEqual(C.data['status'], 'MERGED')
3184
3185 def test_queue_rate_limiting_dependent(self):
3186 "Test that DependentPipelines are rate limited with dep in window"
3187 self.config.set('zuul', 'layout_config',
3188 'tests/fixtures/layout-rate-limit.yaml')
3189 self.sched.reconfigure(self.config)
3190 self.worker.hold_jobs_in_build = True
3191 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3192 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
3193 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
3194
3195 B.setDependsOn(A, 1)
3196
3197 self.worker.addFailTest('project-test1', A)
3198
3199 A.addApproval('CRVW', 2)
3200 B.addApproval('CRVW', 2)
3201 C.addApproval('CRVW', 2)
3202
3203 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3204 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3205 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
3206 self.waitUntilSettled()
3207
3208 # Only A and B will have their merge jobs queued because
3209 # window is 2.
3210 self.assertEqual(len(self.builds), 2)
3211 self.assertEqual(self.builds[0].name, 'project-merge')
3212 self.assertEqual(self.builds[1].name, 'project-merge')
3213
3214 self.worker.release('.*-merge')
3215 self.waitUntilSettled()
3216 self.worker.release('.*-merge')
3217 self.waitUntilSettled()
3218
3219 # Only A and B will have their test jobs queued because
3220 # window is 2.
3221 self.assertEqual(len(self.builds), 4)
3222 self.assertEqual(self.builds[0].name, 'project-test1')
3223 self.assertEqual(self.builds[1].name, 'project-test2')
3224 self.assertEqual(self.builds[2].name, 'project-test1')
3225 self.assertEqual(self.builds[3].name, 'project-test2')
3226
3227 self.worker.release('project-.*')
3228 self.waitUntilSettled()
3229
3230 queue = self.sched.layout.pipelines['gate'].queues[0]
3231 # A failed so window is reduced by 1 to 1.
3232 self.assertEqual(queue.window, 1)
3233 self.assertEqual(queue.window_floor, 1)
3234 self.assertEqual(A.data['status'], 'NEW')
3235 self.assertEqual(B.data['status'], 'NEW')
3236
3237 # Gate is reset and only C's merge job is queued because
3238 # window shrunk to 1 and A and B were dequeued.
3239 self.assertEqual(len(self.builds), 1)
3240 self.assertEqual(self.builds[0].name, 'project-merge')
3241
3242 self.worker.release('.*-merge')
3243 self.waitUntilSettled()
3244
3245 # Only C's test jobs are queued because window is still 1.
3246 self.assertEqual(len(self.builds), 2)
3247 self.assertEqual(self.builds[0].name, 'project-test1')
3248 self.assertEqual(self.builds[1].name, 'project-test2')
3249
3250 self.worker.release('project-.*')
3251 self.waitUntilSettled()
3252
3253 # C was successfully merged so window is increased to 2.
3254 self.assertEqual(queue.window, 2)
3255 self.assertEqual(queue.window_floor, 1)
3256 self.assertEqual(C.data['status'], 'MERGED')
Joshua Heskethba8776a2014-01-12 14:35:40 +08003257
3258 def test_worker_update_metadata(self):
3259 "Test if a worker can send back metadata about itself"
3260 self.worker.hold_jobs_in_build = True
3261
3262 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3263 A.addApproval('CRVW', 2)
3264 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3265 self.waitUntilSettled()
3266
3267 self.assertEqual(len(self.launcher.builds), 1)
3268
3269 self.log.debug('Current builds:')
3270 self.log.debug(self.launcher.builds)
3271
3272 start = time.time()
3273 while True:
3274 if time.time() - start > 10:
3275 raise Exception("Timeout waiting for gearman server to report "
3276 + "back to the client")
3277 build = self.launcher.builds.values()[0]
3278 if build.worker.name == "My Worker":
3279 break
3280 else:
3281 time.sleep(0)
3282
3283 self.log.debug(build)
3284 self.assertEqual("My Worker", build.worker.name)
3285 self.assertEqual("localhost", build.worker.hostname)
3286 self.assertEqual(['127.0.0.1', '192.168.1.1'], build.worker.ips)
3287 self.assertEqual("zuul.example.org", build.worker.fqdn)
3288 self.assertEqual("FakeBuilder", build.worker.program)
3289 self.assertEqual("v1.1", build.worker.version)
3290 self.assertEqual({'something': 'else'}, build.worker.extra)
3291
3292 self.worker.hold_jobs_in_build = False
3293 self.worker.release()
3294 self.waitUntilSettled()
Joshua Hesketh3979e3e2014-03-04 11:21:10 +11003295
3296 def test_footer_message(self):
3297 "Test a pipeline's footer message is correctly added to the report."
3298 self.config.set('zuul', 'layout_config',
3299 'tests/fixtures/layout-footer-message.yaml')
3300 self.sched.reconfigure(self.config)
3301 self.registerJobs()
3302
3303 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3304 A.addApproval('CRVW', 2)
3305 self.worker.addFailTest('test1', A)
3306 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3307 self.waitUntilSettled()
3308
3309 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
3310 B.addApproval('CRVW', 2)
3311 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3312 self.waitUntilSettled()
3313
3314 self.assertEqual(2, len(self.smtp_messages))
3315
3316 failure_body = """\
3317Build failed. For information on how to proceed, see \
3318http://wiki.example.org/Test_Failures
3319
3320- test1 http://logs.example.com/1/1/gate/test1/0 : FAILURE in 0s
3321- test2 http://logs.example.com/1/1/gate/test2/1 : SUCCESS in 0s
3322
3323For CI problems and help debugging, contact ci@example.org"""
3324
3325 success_body = """\
3326Build succeeded.
3327
3328- test1 http://logs.example.com/2/1/gate/test1/2 : SUCCESS in 0s
3329- test2 http://logs.example.com/2/1/gate/test2/3 : SUCCESS in 0s
3330
3331For CI problems and help debugging, contact ci@example.org"""
3332
3333 self.assertEqual(failure_body, self.smtp_messages[0]['body'])
3334 self.assertEqual(success_body, self.smtp_messages[1]['body'])
Joshua Heskethb7179772014-01-30 23:30:46 +11003335
3336 def test_merge_failure_reporters(self):
3337 """Check that the config is set up correctly"""
3338
3339 self.config.set('zuul', 'layout_config',
3340 'tests/fixtures/layout-merge-failure.yaml')
3341 self.sched.reconfigure(self.config)
3342 self.registerJobs()
3343
3344 self.assertEqual(
Jeremy Stanley1c2c3c22015-06-15 21:23:19 +00003345 "Merge Failed.\n\nThis change or one of its cross-repo "
3346 "dependencies was unable to be automatically merged with the "
3347 "current state of its repository. Please rebase the change and "
3348 "upload a new patchset.",
Joshua Heskethb7179772014-01-30 23:30:46 +11003349 self.sched.layout.pipelines['check'].merge_failure_message)
3350 self.assertEqual(
3351 "The merge failed! For more information...",
3352 self.sched.layout.pipelines['gate'].merge_failure_message)
3353
3354 self.assertEqual(
3355 len(self.sched.layout.pipelines['check'].merge_failure_actions), 1)
3356 self.assertEqual(
3357 len(self.sched.layout.pipelines['gate'].merge_failure_actions), 2)
3358
3359 self.assertTrue(isinstance(
Joshua Heskethde958652015-11-10 19:19:50 +11003360 self.sched.layout.pipelines['check'].merge_failure_actions[0],
3361 zuul.reporter.gerrit.GerritReporter))
Joshua Heskethb7179772014-01-30 23:30:46 +11003362
3363 self.assertTrue(
3364 (
3365 isinstance(self.sched.layout.pipelines['gate'].
Joshua Heskethde958652015-11-10 19:19:50 +11003366 merge_failure_actions[0],
Joshua Heskethffe42062014-09-05 21:43:52 +10003367 zuul.reporter.smtp.SMTPReporter) and
Joshua Heskethb7179772014-01-30 23:30:46 +11003368 isinstance(self.sched.layout.pipelines['gate'].
Joshua Heskethde958652015-11-10 19:19:50 +11003369 merge_failure_actions[1],
Joshua Heskethffe42062014-09-05 21:43:52 +10003370 zuul.reporter.gerrit.GerritReporter)
Joshua Heskethb7179772014-01-30 23:30:46 +11003371 ) or (
3372 isinstance(self.sched.layout.pipelines['gate'].
Joshua Heskethde958652015-11-10 19:19:50 +11003373 merge_failure_actions[0],
Joshua Heskethffe42062014-09-05 21:43:52 +10003374 zuul.reporter.gerrit.GerritReporter) and
Joshua Heskethb7179772014-01-30 23:30:46 +11003375 isinstance(self.sched.layout.pipelines['gate'].
Joshua Heskethde958652015-11-10 19:19:50 +11003376 merge_failure_actions[1],
Joshua Heskethffe42062014-09-05 21:43:52 +10003377 zuul.reporter.smtp.SMTPReporter)
Joshua Heskethb7179772014-01-30 23:30:46 +11003378 )
3379 )
3380
3381 def test_merge_failure_reports(self):
3382 """Check that when a change fails to merge the correct message is sent
3383 to the correct reporter"""
3384 self.config.set('zuul', 'layout_config',
3385 'tests/fixtures/layout-merge-failure.yaml')
3386 self.sched.reconfigure(self.config)
3387 self.registerJobs()
3388
3389 # Check a test failure isn't reported to SMTP
3390 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3391 A.addApproval('CRVW', 2)
3392 self.worker.addFailTest('project-test1', A)
3393 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3394 self.waitUntilSettled()
3395
3396 self.assertEqual(3, len(self.history)) # 3 jobs
3397 self.assertEqual(0, len(self.smtp_messages))
3398
3399 # Check a merge failure is reported to SMTP
3400 # B should be merged, but C will conflict with B
3401 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
3402 B.addPatchset(['conflict'])
3403 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
3404 C.addPatchset(['conflict'])
3405 B.addApproval('CRVW', 2)
3406 C.addApproval('CRVW', 2)
3407 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3408 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
3409 self.waitUntilSettled()
3410
3411 self.assertEqual(6, len(self.history)) # A and B jobs
3412 self.assertEqual(1, len(self.smtp_messages))
3413 self.assertEqual('The merge failed! For more information...',
3414 self.smtp_messages[0]['body'])
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11003415
3416 def test_swift_instructions(self):
3417 "Test that the correct swift instructions are sent to the workers"
3418 self.config.set('zuul', 'layout_config',
3419 'tests/fixtures/layout-swift.yaml')
3420 self.sched.reconfigure(self.config)
3421 self.registerJobs()
3422
3423 self.worker.hold_jobs_in_build = True
3424 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3425
3426 A.addApproval('CRVW', 2)
3427 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3428 self.waitUntilSettled()
3429
3430 self.assertEqual(
3431 "https://storage.example.org/V1/AUTH_account/merge_logs/1/1/1/"
3432 "gate/test-merge/",
Joshua Hesketh76dee532014-07-03 15:39:13 +10003433 self.builds[0].parameters['SWIFT_logs_URL'][:-7])
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11003434 self.assertEqual(5,
3435 len(self.builds[0].parameters['SWIFT_logs_HMAC_BODY'].
3436 split('\n')))
3437 self.assertIn('SWIFT_logs_SIGNATURE', self.builds[0].parameters)
3438
3439 self.assertEqual(
3440 "https://storage.example.org/V1/AUTH_account/logs/1/1/1/"
3441 "gate/test-test/",
Joshua Hesketh76dee532014-07-03 15:39:13 +10003442 self.builds[1].parameters['SWIFT_logs_URL'][:-7])
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11003443 self.assertEqual(5,
3444 len(self.builds[1].parameters['SWIFT_logs_HMAC_BODY'].
3445 split('\n')))
3446 self.assertIn('SWIFT_logs_SIGNATURE', self.builds[1].parameters)
3447
3448 self.assertEqual(
3449 "https://storage.example.org/V1/AUTH_account/stash/1/1/1/"
3450 "gate/test-test/",
Joshua Hesketh76dee532014-07-03 15:39:13 +10003451 self.builds[1].parameters['SWIFT_MOSTLY_URL'][:-7])
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11003452 self.assertEqual(5,
3453 len(self.builds[1].
3454 parameters['SWIFT_MOSTLY_HMAC_BODY'].split('\n')))
3455 self.assertIn('SWIFT_MOSTLY_SIGNATURE', self.builds[1].parameters)
3456
3457 self.worker.hold_jobs_in_build = False
3458 self.worker.release()
3459 self.waitUntilSettled()
Joshua Hesketh85af4e92014-02-21 08:28:58 -08003460
3461 def test_client_get_running_jobs(self):
3462 "Test that the RPC client can get a list of running jobs"
3463 self.worker.hold_jobs_in_build = True
3464 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3465 A.addApproval('CRVW', 2)
3466 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3467 self.waitUntilSettled()
3468
3469 client = zuul.rpcclient.RPCClient('127.0.0.1',
3470 self.gearman_server.port)
3471
3472 # Wait for gearman server to send the initial workData back to zuul
3473 start = time.time()
3474 while True:
3475 if time.time() - start > 10:
3476 raise Exception("Timeout waiting for gearman server to report "
3477 + "back to the client")
3478 build = self.launcher.builds.values()[0]
3479 if build.worker.name == "My Worker":
3480 break
3481 else:
3482 time.sleep(0)
3483
3484 running_items = client.get_running_jobs()
3485
3486 self.assertEqual(1, len(running_items))
3487 running_item = running_items[0]
3488 self.assertEqual([], running_item['failing_reasons'])
3489 self.assertEqual([], running_item['items_behind'])
3490 self.assertEqual('https://hostname/1', running_item['url'])
3491 self.assertEqual(None, running_item['item_ahead'])
3492 self.assertEqual('org/project', running_item['project'])
3493 self.assertEqual(None, running_item['remaining_time'])
3494 self.assertEqual(True, running_item['active'])
3495 self.assertEqual('1,1', running_item['id'])
3496
3497 self.assertEqual(3, len(running_item['jobs']))
3498 for job in running_item['jobs']:
3499 if job['name'] == 'project-merge':
3500 self.assertEqual('project-merge', job['name'])
3501 self.assertEqual('gate', job['pipeline'])
3502 self.assertEqual(False, job['retry'])
Joshua Hesketh85af4e92014-02-21 08:28:58 -08003503 self.assertEqual('https://server/job/project-merge/0/',
3504 job['url'])
3505 self.assertEqual(7, len(job['worker']))
3506 self.assertEqual(False, job['canceled'])
3507 self.assertEqual(True, job['voting'])
3508 self.assertEqual(None, job['result'])
3509 self.assertEqual('gate', job['pipeline'])
3510 break
3511
3512 self.worker.hold_jobs_in_build = False
3513 self.worker.release()
3514 self.waitUntilSettled()
3515
3516 running_items = client.get_running_jobs()
3517 self.assertEqual(0, len(running_items))
James E. Blairbadc1ad2014-04-28 13:55:14 -07003518
3519 def test_nonvoting_pipeline(self):
3520 "Test that a nonvoting pipeline (experimental) can still report"
3521
Joshua Heskethcc017ea2014-04-30 19:55:25 +10003522 A = self.fake_gerrit.addFakeChange('org/experimental-project',
3523 'master', 'A')
James E. Blairbadc1ad2014-04-28 13:55:14 -07003524 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3525 self.waitUntilSettled()
Joshua Heskethcc017ea2014-04-30 19:55:25 +10003526 self.assertEqual(
3527 self.getJobFromHistory('experimental-project-test').result,
3528 'SUCCESS')
James E. Blairbadc1ad2014-04-28 13:55:14 -07003529 self.assertEqual(A.reported, 1)
James E. Blair5ee24252014-12-30 10:12:29 -08003530
3531 def test_crd_gate(self):
3532 "Test cross-repo dependencies"
3533 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3534 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3535 A.addApproval('CRVW', 2)
3536 B.addApproval('CRVW', 2)
3537
3538 AM2 = self.fake_gerrit.addFakeChange('org/project1', 'master', 'AM2')
3539 AM1 = self.fake_gerrit.addFakeChange('org/project1', 'master', 'AM1')
3540 AM2.setMerged()
3541 AM1.setMerged()
3542
3543 BM2 = self.fake_gerrit.addFakeChange('org/project2', 'master', 'BM2')
3544 BM1 = self.fake_gerrit.addFakeChange('org/project2', 'master', 'BM1')
3545 BM2.setMerged()
3546 BM1.setMerged()
3547
3548 # A -> AM1 -> AM2
3549 # B -> BM1 -> BM2
3550 # A Depends-On: B
3551 # M2 is here to make sure it is never queried. If it is, it
3552 # means zuul is walking down the entire history of merged
3553 # changes.
3554
3555 B.setDependsOn(BM1, 1)
3556 BM1.setDependsOn(BM2, 1)
3557
3558 A.setDependsOn(AM1, 1)
3559 AM1.setDependsOn(AM2, 1)
3560
3561 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3562 A.subject, B.data['id'])
3563
3564 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3565 self.waitUntilSettled()
3566
3567 self.assertEqual(A.data['status'], 'NEW')
3568 self.assertEqual(B.data['status'], 'NEW')
3569
3570 source = self.sched.layout.pipelines['gate'].source
3571 source.maintainCache([])
3572
3573 self.worker.hold_jobs_in_build = True
3574 B.addApproval('APRV', 1)
3575 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3576 self.waitUntilSettled()
3577
3578 self.worker.release('.*-merge')
3579 self.waitUntilSettled()
3580 self.worker.release('.*-merge')
3581 self.waitUntilSettled()
3582 self.worker.hold_jobs_in_build = False
3583 self.worker.release()
3584 self.waitUntilSettled()
3585
3586 self.assertEqual(AM2.queried, 0)
3587 self.assertEqual(BM2.queried, 0)
3588 self.assertEqual(A.data['status'], 'MERGED')
3589 self.assertEqual(B.data['status'], 'MERGED')
3590 self.assertEqual(A.reported, 2)
3591 self.assertEqual(B.reported, 2)
3592
James E. Blair8f78d882015-02-05 08:51:37 -08003593 self.assertEqual(self.getJobFromHistory('project1-merge').changes,
3594 '2,1 1,1')
3595
3596 def test_crd_branch(self):
3597 "Test cross-repo dependencies in multiple branches"
3598 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3599 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3600 C = self.fake_gerrit.addFakeChange('org/project2', 'mp', 'C')
3601 C.data['id'] = B.data['id']
3602 A.addApproval('CRVW', 2)
3603 B.addApproval('CRVW', 2)
3604 C.addApproval('CRVW', 2)
3605
3606 # A Depends-On: B+C
3607 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3608 A.subject, B.data['id'])
3609
3610 self.worker.hold_jobs_in_build = True
3611 B.addApproval('APRV', 1)
3612 C.addApproval('APRV', 1)
3613 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3614 self.waitUntilSettled()
3615
3616 self.worker.release('.*-merge')
3617 self.waitUntilSettled()
3618 self.worker.release('.*-merge')
3619 self.waitUntilSettled()
3620 self.worker.release('.*-merge')
3621 self.waitUntilSettled()
3622 self.worker.hold_jobs_in_build = False
3623 self.worker.release()
3624 self.waitUntilSettled()
3625
3626 self.assertEqual(A.data['status'], 'MERGED')
3627 self.assertEqual(B.data['status'], 'MERGED')
3628 self.assertEqual(C.data['status'], 'MERGED')
3629 self.assertEqual(A.reported, 2)
3630 self.assertEqual(B.reported, 2)
3631 self.assertEqual(C.reported, 2)
3632
3633 self.assertEqual(self.getJobFromHistory('project1-merge').changes,
3634 '2,1 3,1 1,1')
3635
3636 def test_crd_multiline(self):
3637 "Test multiple depends-on lines in commit"
3638 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3639 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3640 C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
3641 A.addApproval('CRVW', 2)
3642 B.addApproval('CRVW', 2)
3643 C.addApproval('CRVW', 2)
3644
3645 # A Depends-On: B+C
3646 A.data['commitMessage'] = '%s\n\nDepends-On: %s\nDepends-On: %s\n' % (
3647 A.subject, B.data['id'], C.data['id'])
3648
3649 self.worker.hold_jobs_in_build = True
3650 B.addApproval('APRV', 1)
3651 C.addApproval('APRV', 1)
3652 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3653 self.waitUntilSettled()
3654
3655 self.worker.release('.*-merge')
3656 self.waitUntilSettled()
3657 self.worker.release('.*-merge')
3658 self.waitUntilSettled()
3659 self.worker.release('.*-merge')
3660 self.waitUntilSettled()
3661 self.worker.hold_jobs_in_build = False
3662 self.worker.release()
3663 self.waitUntilSettled()
3664
3665 self.assertEqual(A.data['status'], 'MERGED')
3666 self.assertEqual(B.data['status'], 'MERGED')
3667 self.assertEqual(C.data['status'], 'MERGED')
3668 self.assertEqual(A.reported, 2)
3669 self.assertEqual(B.reported, 2)
3670 self.assertEqual(C.reported, 2)
3671
3672 self.assertEqual(self.getJobFromHistory('project1-merge').changes,
3673 '2,1 3,1 1,1')
James E. Blair5ee24252014-12-30 10:12:29 -08003674
3675 def test_crd_unshared_gate(self):
3676 "Test cross-repo dependencies in unshared gate queues"
3677 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3678 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
3679 A.addApproval('CRVW', 2)
3680 B.addApproval('CRVW', 2)
3681
3682 # A Depends-On: B
3683 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3684 A.subject, B.data['id'])
3685
3686 # A and B do not share a queue, make sure that A is unable to
3687 # enqueue B (and therefore, A is unable to be enqueued).
3688 B.addApproval('APRV', 1)
3689 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3690 self.waitUntilSettled()
3691
3692 self.assertEqual(A.data['status'], 'NEW')
3693 self.assertEqual(B.data['status'], 'NEW')
3694 self.assertEqual(A.reported, 0)
3695 self.assertEqual(B.reported, 0)
3696 self.assertEqual(len(self.history), 0)
3697
3698 # Enqueue and merge B alone.
3699 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3700 self.waitUntilSettled()
3701
3702 self.assertEqual(B.data['status'], 'MERGED')
3703 self.assertEqual(B.reported, 2)
3704
3705 # Now that B is merged, A should be able to be enqueued and
3706 # merged.
3707 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3708 self.waitUntilSettled()
3709
3710 self.assertEqual(A.data['status'], 'MERGED')
3711 self.assertEqual(A.reported, 2)
3712
James E. Blair96698e22015-04-02 07:48:21 -07003713 def test_crd_gate_reverse(self):
3714 "Test reverse cross-repo dependencies"
3715 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3716 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3717 A.addApproval('CRVW', 2)
3718 B.addApproval('CRVW', 2)
3719
3720 # A Depends-On: B
3721
3722 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3723 A.subject, B.data['id'])
3724
3725 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3726 self.waitUntilSettled()
3727
3728 self.assertEqual(A.data['status'], 'NEW')
3729 self.assertEqual(B.data['status'], 'NEW')
3730
3731 self.worker.hold_jobs_in_build = True
3732 A.addApproval('APRV', 1)
3733 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3734 self.waitUntilSettled()
3735
3736 self.worker.release('.*-merge')
3737 self.waitUntilSettled()
3738 self.worker.release('.*-merge')
3739 self.waitUntilSettled()
3740 self.worker.hold_jobs_in_build = False
3741 self.worker.release()
3742 self.waitUntilSettled()
3743
3744 self.assertEqual(A.data['status'], 'MERGED')
3745 self.assertEqual(B.data['status'], 'MERGED')
3746 self.assertEqual(A.reported, 2)
3747 self.assertEqual(B.reported, 2)
3748
3749 self.assertEqual(self.getJobFromHistory('project1-merge').changes,
3750 '2,1 1,1')
3751
James E. Blair5ee24252014-12-30 10:12:29 -08003752 def test_crd_cycle(self):
3753 "Test cross-repo dependency cycles"
3754 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3755 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3756 A.addApproval('CRVW', 2)
3757 B.addApproval('CRVW', 2)
3758
3759 # A -> B -> A (via commit-depends)
3760
3761 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3762 A.subject, B.data['id'])
3763 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3764 B.subject, A.data['id'])
3765
3766 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3767 self.waitUntilSettled()
3768
3769 self.assertEqual(A.reported, 0)
3770 self.assertEqual(B.reported, 0)
3771 self.assertEqual(A.data['status'], 'NEW')
3772 self.assertEqual(B.data['status'], 'NEW')
James E. Blairbfb8e042014-12-30 17:01:44 -08003773
Evgeny Antyshev0deaaad2015-08-03 20:22:56 +00003774 def test_crd_gate_unknown(self):
3775 "Test unknown projects in dependent pipeline"
3776 self.init_repo("org/unknown")
3777 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3778 B = self.fake_gerrit.addFakeChange('org/unknown', 'master', 'B')
3779 A.addApproval('CRVW', 2)
3780 B.addApproval('CRVW', 2)
3781
3782 # A Depends-On: B
3783 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3784 A.subject, B.data['id'])
3785
3786 B.addApproval('APRV', 1)
3787 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3788 self.waitUntilSettled()
3789
3790 # Unknown projects cannot share a queue with any other
3791 # since they don't have common jobs with any other (they have no jobs).
3792 # Changes which depend on unknown project changes
3793 # should not be processed in dependent pipeline
3794 self.assertEqual(A.data['status'], 'NEW')
3795 self.assertEqual(B.data['status'], 'NEW')
3796 self.assertEqual(A.reported, 0)
3797 self.assertEqual(B.reported, 0)
3798 self.assertEqual(len(self.history), 0)
3799
3800 # Simulate change B being gated outside this layout
3801 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3802 B.setMerged()
3803 self.waitUntilSettled()
3804 self.assertEqual(len(self.history), 0)
3805
3806 # Now that B is merged, A should be able to be enqueued and
3807 # merged.
3808 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3809 self.waitUntilSettled()
3810
3811 self.assertEqual(A.data['status'], 'MERGED')
3812 self.assertEqual(A.reported, 2)
3813 self.assertEqual(B.data['status'], 'MERGED')
3814 self.assertEqual(B.reported, 0)
3815
James E. Blairbfb8e042014-12-30 17:01:44 -08003816 def test_crd_check(self):
3817 "Test cross-repo dependencies in independent pipelines"
3818
3819 self.gearman_server.hold_jobs_in_queue = True
3820 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3821 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3822
3823 # A Depends-On: B
3824 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3825 A.subject, B.data['id'])
3826
3827 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3828 self.waitUntilSettled()
3829
3830 queue = self.gearman_server.getQueue()
3831 ref = self.getParameter(queue[-1], 'ZUUL_REF')
3832 self.gearman_server.hold_jobs_in_queue = False
3833 self.gearman_server.release()
3834 self.waitUntilSettled()
3835
3836 path = os.path.join(self.git_root, "org/project1")
3837 repo = git.Repo(path)
3838 repo_messages = [c.message.strip() for c in repo.iter_commits(ref)]
3839 repo_messages.reverse()
3840 correct_messages = ['initial commit', 'A-1']
3841 self.assertEqual(repo_messages, correct_messages)
3842
3843 path = os.path.join(self.git_root, "org/project2")
3844 repo = git.Repo(path)
3845 repo_messages = [c.message.strip() for c in repo.iter_commits(ref)]
3846 repo_messages.reverse()
3847 correct_messages = ['initial commit', 'B-1']
3848 self.assertEqual(repo_messages, correct_messages)
3849
3850 self.assertEqual(A.data['status'], 'NEW')
3851 self.assertEqual(B.data['status'], 'NEW')
3852 self.assertEqual(A.reported, 1)
3853 self.assertEqual(B.reported, 0)
3854
3855 self.assertEqual(self.history[0].changes, '2,1 1,1')
3856 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 0)
James E. Blair8f78d882015-02-05 08:51:37 -08003857
James E. Blairdbfe1cd2015-02-07 11:41:19 -08003858 def test_crd_check_git_depends(self):
3859 "Test single-repo dependencies in independent pipelines"
James E. Blairb8c16472015-05-05 14:55:26 -07003860 self.gearman_server.hold_jobs_in_build = True
James E. Blairdbfe1cd2015-02-07 11:41:19 -08003861 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3862 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
3863
3864 # Add two git-dependent changes and make sure they both report
3865 # success.
3866 B.setDependsOn(A, 1)
3867 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3868 self.waitUntilSettled()
3869 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
3870 self.waitUntilSettled()
3871
James E. Blairb8c16472015-05-05 14:55:26 -07003872 self.orderedRelease()
3873 self.gearman_server.hold_jobs_in_build = False
James E. Blairdbfe1cd2015-02-07 11:41:19 -08003874 self.waitUntilSettled()
3875
3876 self.assertEqual(A.data['status'], 'NEW')
3877 self.assertEqual(B.data['status'], 'NEW')
3878 self.assertEqual(A.reported, 1)
3879 self.assertEqual(B.reported, 1)
3880
3881 self.assertEqual(self.history[0].changes, '1,1')
3882 self.assertEqual(self.history[-1].changes, '1,1 2,1')
3883 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 0)
3884
3885 self.assertIn('Build succeeded', A.messages[0])
3886 self.assertIn('Build succeeded', B.messages[0])
3887
3888 def test_crd_check_duplicate(self):
3889 "Test duplicate check in independent pipelines"
James E. Blair1e263032015-05-07 14:35:34 -07003890 self.worker.hold_jobs_in_build = True
James E. Blairdbfe1cd2015-02-07 11:41:19 -08003891 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3892 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
3893 check_pipeline = self.sched.layout.pipelines['check']
3894
3895 # Add two git-dependent changes...
3896 B.setDependsOn(A, 1)
3897 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
3898 self.waitUntilSettled()
3899 self.assertEqual(len(check_pipeline.getAllItems()), 2)
3900
3901 # ...make sure the live one is not duplicated...
3902 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
3903 self.waitUntilSettled()
3904 self.assertEqual(len(check_pipeline.getAllItems()), 2)
3905
3906 # ...but the non-live one is able to be.
3907 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3908 self.waitUntilSettled()
3909 self.assertEqual(len(check_pipeline.getAllItems()), 3)
3910
Clark Boylandd849822015-03-02 12:38:14 -08003911 # Release jobs in order to avoid races with change A jobs
3912 # finishing before change B jobs.
James E. Blaird7650852015-05-07 15:47:37 -07003913 self.orderedRelease()
James E. Blair1e263032015-05-07 14:35:34 -07003914 self.worker.hold_jobs_in_build = False
3915 self.worker.release()
James E. Blairdbfe1cd2015-02-07 11:41:19 -08003916 self.waitUntilSettled()
3917
3918 self.assertEqual(A.data['status'], 'NEW')
3919 self.assertEqual(B.data['status'], 'NEW')
3920 self.assertEqual(A.reported, 1)
3921 self.assertEqual(B.reported, 1)
3922
3923 self.assertEqual(self.history[0].changes, '1,1 2,1')
3924 self.assertEqual(self.history[1].changes, '1,1')
3925 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 0)
3926
3927 self.assertIn('Build succeeded', A.messages[0])
3928 self.assertIn('Build succeeded', B.messages[0])
3929
Evgeny Antyshev0deaaad2015-08-03 20:22:56 +00003930 def _test_crd_check_reconfiguration(self, project1, project2):
James E. Blair8f78d882015-02-05 08:51:37 -08003931 "Test cross-repo dependencies re-enqueued in independent pipelines"
3932
3933 self.gearman_server.hold_jobs_in_queue = True
Evgeny Antyshev0deaaad2015-08-03 20:22:56 +00003934 A = self.fake_gerrit.addFakeChange(project1, 'master', 'A')
3935 B = self.fake_gerrit.addFakeChange(project2, 'master', 'B')
James E. Blair8f78d882015-02-05 08:51:37 -08003936
3937 # A Depends-On: B
3938 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3939 A.subject, B.data['id'])
3940
3941 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3942 self.waitUntilSettled()
3943
3944 self.sched.reconfigure(self.config)
3945
3946 # Make sure the items still share a change queue, and the
3947 # first one is not live.
3948 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 1)
3949 queue = self.sched.layout.pipelines['check'].queues[0]
3950 first_item = queue.queue[0]
3951 for item in queue.queue:
3952 self.assertEqual(item.queue, first_item.queue)
3953 self.assertFalse(first_item.live)
3954 self.assertTrue(queue.queue[1].live)
3955
3956 self.gearman_server.hold_jobs_in_queue = False
3957 self.gearman_server.release()
3958 self.waitUntilSettled()
3959
3960 self.assertEqual(A.data['status'], 'NEW')
3961 self.assertEqual(B.data['status'], 'NEW')
3962 self.assertEqual(A.reported, 1)
3963 self.assertEqual(B.reported, 0)
3964
3965 self.assertEqual(self.history[0].changes, '2,1 1,1')
3966 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 0)
James E. Blair17dd6772015-02-09 14:45:18 -08003967
Evgeny Antyshev0deaaad2015-08-03 20:22:56 +00003968 def test_crd_check_reconfiguration(self):
3969 self._test_crd_check_reconfiguration('org/project1', 'org/project2')
3970
3971 def test_crd_undefined_project(self):
3972 """Test that undefined projects in dependencies are handled for
3973 independent pipelines"""
3974 # It's a hack for fake gerrit,
3975 # as it implies repo creation upon the creation of any change
3976 self.init_repo("org/unknown")
3977 self._test_crd_check_reconfiguration('org/project1', 'org/unknown')
3978
James E. Blair17dd6772015-02-09 14:45:18 -08003979 def test_crd_check_ignore_dependencies(self):
3980 "Test cross-repo dependencies can be ignored"
3981 self.config.set('zuul', 'layout_config',
3982 'tests/fixtures/layout-ignore-dependencies.yaml')
3983 self.sched.reconfigure(self.config)
3984 self.registerJobs()
3985
3986 self.gearman_server.hold_jobs_in_queue = True
3987 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3988 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3989 C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
3990
3991 # A Depends-On: B
3992 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3993 A.subject, B.data['id'])
3994 # C git-depends on B
3995 C.setDependsOn(B, 1)
3996 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3997 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
3998 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
3999 self.waitUntilSettled()
4000
4001 # Make sure none of the items share a change queue, and all
4002 # are live.
4003 check_pipeline = self.sched.layout.pipelines['check']
4004 self.assertEqual(len(check_pipeline.queues), 3)
4005 self.assertEqual(len(check_pipeline.getAllItems()), 3)
4006 for item in check_pipeline.getAllItems():
4007 self.assertTrue(item.live)
4008
4009 self.gearman_server.hold_jobs_in_queue = False
4010 self.gearman_server.release()
4011 self.waitUntilSettled()
4012
4013 self.assertEqual(A.data['status'], 'NEW')
4014 self.assertEqual(B.data['status'], 'NEW')
4015 self.assertEqual(C.data['status'], 'NEW')
4016 self.assertEqual(A.reported, 1)
4017 self.assertEqual(B.reported, 1)
4018 self.assertEqual(C.reported, 1)
4019
4020 # Each job should have tested exactly one change
4021 for job in self.history:
4022 self.assertEqual(len(job.changes.split()), 1)
James E. Blair96698e22015-04-02 07:48:21 -07004023
4024 def test_crd_check_transitive(self):
4025 "Test transitive cross-repo dependencies"
4026 # Specifically, if A -> B -> C, and C gets a new patchset and
4027 # A gets a new patchset, ensure the test of A,2 includes B,1
4028 # and C,2 (not C,1 which would indicate stale data in the
4029 # cache for B).
4030 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
4031 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
4032 C = self.fake_gerrit.addFakeChange('org/project3', 'master', 'C')
4033
4034 # A Depends-On: B
4035 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
4036 A.subject, B.data['id'])
4037
4038 # B Depends-On: C
4039 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
4040 B.subject, C.data['id'])
4041
4042 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
4043 self.waitUntilSettled()
4044 self.assertEqual(self.history[-1].changes, '3,1 2,1 1,1')
4045
4046 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
4047 self.waitUntilSettled()
4048 self.assertEqual(self.history[-1].changes, '3,1 2,1')
4049
4050 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
4051 self.waitUntilSettled()
4052 self.assertEqual(self.history[-1].changes, '3,1')
4053
4054 C.addPatchset()
4055 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(2))
4056 self.waitUntilSettled()
4057 self.assertEqual(self.history[-1].changes, '3,2')
4058
4059 A.addPatchset()
4060 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
4061 self.waitUntilSettled()
4062 self.assertEqual(self.history[-1].changes, '3,2 2,1 1,2')
Joshua Hesketh89e829d2015-02-10 16:29:45 +11004063
4064 def test_disable_at(self):
4065 "Test a pipeline will only report to the disabled trigger when failing"
4066
4067 self.config.set('zuul', 'layout_config',
4068 'tests/fixtures/layout-disable-at.yaml')
4069 self.sched.reconfigure(self.config)
4070
4071 self.assertEqual(3, self.sched.layout.pipelines['check'].disable_at)
4072 self.assertEqual(
4073 0, self.sched.layout.pipelines['check']._consecutive_failures)
4074 self.assertFalse(self.sched.layout.pipelines['check']._disabled)
4075
4076 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
4077 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
4078 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
4079 D = self.fake_gerrit.addFakeChange('org/project', 'master', 'D')
4080 E = self.fake_gerrit.addFakeChange('org/project', 'master', 'E')
4081 F = self.fake_gerrit.addFakeChange('org/project', 'master', 'F')
4082 G = self.fake_gerrit.addFakeChange('org/project', 'master', 'G')
4083 H = self.fake_gerrit.addFakeChange('org/project', 'master', 'H')
4084 I = self.fake_gerrit.addFakeChange('org/project', 'master', 'I')
4085 J = self.fake_gerrit.addFakeChange('org/project', 'master', 'J')
4086 K = self.fake_gerrit.addFakeChange('org/project', 'master', 'K')
4087
4088 self.worker.addFailTest('project-test1', A)
4089 self.worker.addFailTest('project-test1', B)
4090 # Let C pass, resetting the counter
4091 self.worker.addFailTest('project-test1', D)
4092 self.worker.addFailTest('project-test1', E)
4093 self.worker.addFailTest('project-test1', F)
4094 self.worker.addFailTest('project-test1', G)
4095 self.worker.addFailTest('project-test1', H)
4096 # I also passes but should only report to the disabled reporters
4097 self.worker.addFailTest('project-test1', J)
4098 self.worker.addFailTest('project-test1', K)
4099
4100 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
4101 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
4102 self.waitUntilSettled()
4103
4104 self.assertEqual(
4105 2, self.sched.layout.pipelines['check']._consecutive_failures)
4106 self.assertFalse(self.sched.layout.pipelines['check']._disabled)
4107
4108 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
4109 self.waitUntilSettled()
4110
4111 self.assertEqual(
4112 0, self.sched.layout.pipelines['check']._consecutive_failures)
4113 self.assertFalse(self.sched.layout.pipelines['check']._disabled)
4114
4115 self.fake_gerrit.addEvent(D.getPatchsetCreatedEvent(1))
4116 self.fake_gerrit.addEvent(E.getPatchsetCreatedEvent(1))
4117 self.fake_gerrit.addEvent(F.getPatchsetCreatedEvent(1))
4118 self.waitUntilSettled()
4119
4120 # We should be disabled now
4121 self.assertEqual(
4122 3, self.sched.layout.pipelines['check']._consecutive_failures)
4123 self.assertTrue(self.sched.layout.pipelines['check']._disabled)
4124
4125 # We need to wait between each of these patches to make sure the
4126 # smtp messages come back in an expected order
4127 self.fake_gerrit.addEvent(G.getPatchsetCreatedEvent(1))
4128 self.waitUntilSettled()
4129 self.fake_gerrit.addEvent(H.getPatchsetCreatedEvent(1))
4130 self.waitUntilSettled()
4131 self.fake_gerrit.addEvent(I.getPatchsetCreatedEvent(1))
4132 self.waitUntilSettled()
4133
4134 # The first 6 (ABCDEF) jobs should have reported back to gerrt thus
4135 # leaving a message on each change
4136 self.assertEqual(1, len(A.messages))
4137 self.assertIn('Build failed.', A.messages[0])
4138 self.assertEqual(1, len(B.messages))
4139 self.assertIn('Build failed.', B.messages[0])
4140 self.assertEqual(1, len(C.messages))
4141 self.assertIn('Build succeeded.', C.messages[0])
4142 self.assertEqual(1, len(D.messages))
4143 self.assertIn('Build failed.', D.messages[0])
4144 self.assertEqual(1, len(E.messages))
4145 self.assertIn('Build failed.', E.messages[0])
4146 self.assertEqual(1, len(F.messages))
4147 self.assertIn('Build failed.', F.messages[0])
4148
4149 # The last 3 (GHI) would have only reported via smtp.
4150 self.assertEqual(3, len(self.smtp_messages))
4151 self.assertEqual(0, len(G.messages))
4152 self.assertIn('Build failed.', self.smtp_messages[0]['body'])
4153 self.assertIn('/7/1/check', self.smtp_messages[0]['body'])
4154 self.assertEqual(0, len(H.messages))
4155 self.assertIn('Build failed.', self.smtp_messages[1]['body'])
4156 self.assertIn('/8/1/check', self.smtp_messages[1]['body'])
4157 self.assertEqual(0, len(I.messages))
4158 self.assertIn('Build succeeded.', self.smtp_messages[2]['body'])
4159 self.assertIn('/9/1/check', self.smtp_messages[2]['body'])
4160
4161 # Now reload the configuration (simulate a HUP) to check the pipeline
4162 # comes out of disabled
4163 self.sched.reconfigure(self.config)
4164
4165 self.assertEqual(3, self.sched.layout.pipelines['check'].disable_at)
4166 self.assertEqual(
4167 0, self.sched.layout.pipelines['check']._consecutive_failures)
4168 self.assertFalse(self.sched.layout.pipelines['check']._disabled)
4169
4170 self.fake_gerrit.addEvent(J.getPatchsetCreatedEvent(1))
4171 self.fake_gerrit.addEvent(K.getPatchsetCreatedEvent(1))
4172 self.waitUntilSettled()
4173
4174 self.assertEqual(
4175 2, self.sched.layout.pipelines['check']._consecutive_failures)
4176 self.assertFalse(self.sched.layout.pipelines['check']._disabled)
4177
4178 # J and K went back to gerrit
4179 self.assertEqual(1, len(J.messages))
4180 self.assertIn('Build failed.', J.messages[0])
4181 self.assertEqual(1, len(K.messages))
4182 self.assertIn('Build failed.', K.messages[0])
4183 # No more messages reported via smtp
4184 self.assertEqual(3, len(self.smtp_messages))