blob: 19acc9b59ce77c649e3547f13afb2997f4faee6e [file] [log] [blame]
James E. Blairb0fcae42012-07-17 11:12:10 -07001#!/usr/bin/env python
2
3# Copyright 2012 Hewlett-Packard Development Company, L.P.
4#
5# Licensed under the Apache License, Version 2.0 (the "License"); you may
6# not use this file except in compliance with the License. You may obtain
7# a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations
15# under the License.
16
James E. Blairb0fcae42012-07-17 11:12:10 -070017import json
Monty Taylorbc758832013-06-17 17:22:42 -040018import logging
19import os
James E. Blairb0fcae42012-07-17 11:12:10 -070020import re
James E. Blair4886cc12012-07-18 15:39:41 -070021import shutil
Monty Taylorbc758832013-06-17 17:22:42 -040022import time
James E. Blair1843a552013-07-03 14:19:52 -070023import urllib
Monty Taylorbc758832013-06-17 17:22:42 -040024import urllib2
Maru Newby3fe5f852015-01-13 04:22:14 +000025import yaml
Monty Taylorbc758832013-06-17 17:22:42 -040026
James E. Blair4886cc12012-07-18 15:39:41 -070027import git
Monty Taylorbc758832013-06-17 17:22:42 -040028import testtools
James E. Blairb0fcae42012-07-17 11:12:10 -070029
Maru Newby3fe5f852015-01-13 04:22:14 +000030import zuul.change_matcher
James E. Blairb0fcae42012-07-17 11:12:10 -070031import zuul.scheduler
James E. Blairad28e912013-11-27 10:43:22 -080032import zuul.rpcclient
Joshua Hesketh1879cf72013-08-19 14:13:15 +100033import zuul.reporter.gerrit
Joshua Hesketh5fea8672013-08-19 17:32:01 +100034import zuul.reporter.smtp
James E. Blairb0fcae42012-07-17 11:12:10 -070035
Maru Newby3fe5f852015-01-13 04:22:14 +000036from tests.base import (
37 BaseTestCase,
38 ZuulTestCase,
39 repack_repo,
40)
James E. Blairb0fcae42012-07-17 11:12:10 -070041
James E. Blair1f4c2bb2013-04-26 08:40:46 -070042logging.basicConfig(level=logging.DEBUG,
43 format='%(asctime)s %(name)-32s '
44 '%(levelname)-8s %(message)s')
James E. Blairb0fcae42012-07-17 11:12:10 -070045
46
Maru Newby3fe5f852015-01-13 04:22:14 +000047class TestSchedulerConfigParsing(BaseTestCase):
48
49 def test_parse_skip_if(self):
50 job_yaml = """
51jobs:
52 - name: job_name
53 skip-if:
54 - project: ^project_name$
55 branch: ^stable/icehouse$
56 all-files-match-any:
57 - ^filename$
58 - project: ^project2_name$
59 all-files-match-any:
60 - ^filename2$
61 """.strip()
62 data = yaml.load(job_yaml)
63 config_job = data.get('jobs')[0]
64 sched = zuul.scheduler.Scheduler()
65 cm = zuul.change_matcher
66 expected = cm.MatchAny([
67 cm.MatchAll([
68 cm.ProjectMatcher('^project_name$'),
69 cm.BranchMatcher('^stable/icehouse$'),
70 cm.MatchAllFiles([cm.FileMatcher('^filename$')]),
71 ]),
72 cm.MatchAll([
73 cm.ProjectMatcher('^project2_name$'),
74 cm.MatchAllFiles([cm.FileMatcher('^filename2$')]),
75 ]),
76 ])
77 matcher = sched._parseSkipIf(config_job)
78 self.assertEqual(expected, matcher)
79
80
Clark Boylanb640e052014-04-03 16:41:46 -070081class TestScheduler(ZuulTestCase):
Antoine Mussobd86a312014-01-08 14:51:33 +010082
James E. Blairb0fcae42012-07-17 11:12:10 -070083 def test_jobs_launched(self):
84 "Test that jobs are launched and a change is merged"
James E. Blair1f4c2bb2013-04-26 08:40:46 -070085
James E. Blairb0fcae42012-07-17 11:12:10 -070086 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
James E. Blair8c803f82012-07-31 16:25:42 -070087 A.addApproval('CRVW', 2)
James E. Blairb0fcae42012-07-17 11:12:10 -070088 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
89 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -040090 self.assertEqual(self.getJobFromHistory('project-merge').result,
91 'SUCCESS')
92 self.assertEqual(self.getJobFromHistory('project-test1').result,
93 'SUCCESS')
94 self.assertEqual(self.getJobFromHistory('project-test2').result,
95 'SUCCESS')
96 self.assertEqual(A.data['status'], 'MERGED')
97 self.assertEqual(A.reported, 2)
James E. Blairb0fcae42012-07-17 11:12:10 -070098
James E. Blair66eeebf2013-07-27 17:44:32 -070099 self.assertReportedStat('gerrit.event.comment-added', value='1|c')
100 self.assertReportedStat('zuul.pipeline.gate.current_changes',
101 value='1|g')
102 self.assertReportedStat('zuul.pipeline.gate.job.project-merge.SUCCESS',
103 kind='ms')
104 self.assertReportedStat('zuul.pipeline.gate.job.project-merge.SUCCESS',
105 value='1|c')
106 self.assertReportedStat('zuul.pipeline.gate.resident_time', kind='ms')
107 self.assertReportedStat('zuul.pipeline.gate.total_changes',
108 value='1|c')
James E. Blair412e5582013-04-22 15:50:12 -0700109 self.assertReportedStat(
James E. Blair66eeebf2013-07-27 17:44:32 -0700110 'zuul.pipeline.gate.org.project.resident_time', kind='ms')
James E. Blair412e5582013-04-22 15:50:12 -0700111 self.assertReportedStat(
James E. Blair66eeebf2013-07-27 17:44:32 -0700112 'zuul.pipeline.gate.org.project.total_changes', value='1|c')
James E. Blair412e5582013-04-22 15:50:12 -0700113
James E. Blair3cb10702013-08-24 08:56:03 -0700114 def test_initial_pipeline_gauges(self):
115 "Test that each pipeline reported its length on start"
116 pipeline_names = self.sched.layout.pipelines.keys()
117 self.assertNotEqual(len(pipeline_names), 0)
118 for name in pipeline_names:
119 self.assertReportedStat('zuul.pipeline.%s.current_changes' % name,
120 value='0|g')
121
James E. Blair42f74822013-05-14 15:18:03 -0700122 def test_duplicate_pipelines(self):
123 "Test that a change matching multiple pipelines works"
James E. Blair1b4d9722013-05-21 10:32:04 -0700124
James E. Blair42f74822013-05-14 15:18:03 -0700125 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
126 self.fake_gerrit.addEvent(A.getChangeRestoredEvent())
127 self.waitUntilSettled()
James E. Blair42f74822013-05-14 15:18:03 -0700128
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400129 self.assertEqual(len(self.history), 2)
Monty Taylor6bef8ef2013-06-02 08:17:12 -0400130 self.history[0].name == 'project-test1'
131 self.history[1].name == 'project-test1'
James E. Blair42f74822013-05-14 15:18:03 -0700132
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400133 self.assertEqual(len(A.messages), 2)
James E. Blair42f74822013-05-14 15:18:03 -0700134 if 'dup1/project-test1' in A.messages[0]:
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400135 self.assertIn('dup1/project-test1', A.messages[0])
136 self.assertNotIn('dup2/project-test1', A.messages[0])
137 self.assertNotIn('dup1/project-test1', A.messages[1])
138 self.assertIn('dup2/project-test1', A.messages[1])
James E. Blair42f74822013-05-14 15:18:03 -0700139 else:
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400140 self.assertIn('dup1/project-test1', A.messages[1])
141 self.assertNotIn('dup2/project-test1', A.messages[1])
142 self.assertNotIn('dup1/project-test1', A.messages[0])
143 self.assertIn('dup2/project-test1', A.messages[0])
James E. Blair42f74822013-05-14 15:18:03 -0700144
James E. Blairb0fcae42012-07-17 11:12:10 -0700145 def test_parallel_changes(self):
146 "Test that changes are tested in parallel and merged in series"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700147
148 self.worker.hold_jobs_in_build = True
James E. Blairb0fcae42012-07-17 11:12:10 -0700149 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
150 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
151 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
James E. Blair8c803f82012-07-31 16:25:42 -0700152 A.addApproval('CRVW', 2)
153 B.addApproval('CRVW', 2)
154 C.addApproval('CRVW', 2)
James E. Blairb0fcae42012-07-17 11:12:10 -0700155
156 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
157 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
158 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
159
160 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400161 self.assertEqual(len(self.builds), 1)
162 self.assertEqual(self.builds[0].name, 'project-merge')
163 self.assertTrue(self.job_has_changes(self.builds[0], A))
James E. Blairb0fcae42012-07-17 11:12:10 -0700164
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700165 self.worker.release('.*-merge')
James E. Blairb0fcae42012-07-17 11:12:10 -0700166 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400167 self.assertEqual(len(self.builds), 3)
168 self.assertEqual(self.builds[0].name, 'project-test1')
169 self.assertTrue(self.job_has_changes(self.builds[0], A))
170 self.assertEqual(self.builds[1].name, 'project-test2')
171 self.assertTrue(self.job_has_changes(self.builds[1], A))
172 self.assertEqual(self.builds[2].name, 'project-merge')
173 self.assertTrue(self.job_has_changes(self.builds[2], A, B))
James E. Blairb0fcae42012-07-17 11:12:10 -0700174
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700175 self.worker.release('.*-merge')
James E. Blairb0fcae42012-07-17 11:12:10 -0700176 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400177 self.assertEqual(len(self.builds), 5)
178 self.assertEqual(self.builds[0].name, 'project-test1')
179 self.assertTrue(self.job_has_changes(self.builds[0], A))
180 self.assertEqual(self.builds[1].name, 'project-test2')
181 self.assertTrue(self.job_has_changes(self.builds[1], A))
James E. Blairb0fcae42012-07-17 11:12:10 -0700182
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400183 self.assertEqual(self.builds[2].name, 'project-test1')
184 self.assertTrue(self.job_has_changes(self.builds[2], A, B))
185 self.assertEqual(self.builds[3].name, 'project-test2')
186 self.assertTrue(self.job_has_changes(self.builds[3], A, B))
James E. Blairb0fcae42012-07-17 11:12:10 -0700187
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400188 self.assertEqual(self.builds[4].name, 'project-merge')
189 self.assertTrue(self.job_has_changes(self.builds[4], A, B, C))
James E. Blairb0fcae42012-07-17 11:12:10 -0700190
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700191 self.worker.release('.*-merge')
James E. Blairb0fcae42012-07-17 11:12:10 -0700192 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400193 self.assertEqual(len(self.builds), 6)
194 self.assertEqual(self.builds[0].name, 'project-test1')
195 self.assertTrue(self.job_has_changes(self.builds[0], A))
196 self.assertEqual(self.builds[1].name, 'project-test2')
197 self.assertTrue(self.job_has_changes(self.builds[1], A))
James E. Blairb0fcae42012-07-17 11:12:10 -0700198
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400199 self.assertEqual(self.builds[2].name, 'project-test1')
200 self.assertTrue(self.job_has_changes(self.builds[2], A, B))
201 self.assertEqual(self.builds[3].name, 'project-test2')
202 self.assertTrue(self.job_has_changes(self.builds[3], A, B))
James E. Blairb0fcae42012-07-17 11:12:10 -0700203
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400204 self.assertEqual(self.builds[4].name, 'project-test1')
205 self.assertTrue(self.job_has_changes(self.builds[4], A, B, C))
206 self.assertEqual(self.builds[5].name, 'project-test2')
207 self.assertTrue(self.job_has_changes(self.builds[5], A, B, C))
James E. Blairb0fcae42012-07-17 11:12:10 -0700208
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700209 self.worker.hold_jobs_in_build = False
210 self.worker.release()
James E. Blairb0fcae42012-07-17 11:12:10 -0700211 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400212 self.assertEqual(len(self.builds), 0)
James E. Blairb0fcae42012-07-17 11:12:10 -0700213
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400214 self.assertEqual(len(self.history), 9)
215 self.assertEqual(A.data['status'], 'MERGED')
216 self.assertEqual(B.data['status'], 'MERGED')
217 self.assertEqual(C.data['status'], 'MERGED')
218 self.assertEqual(A.reported, 2)
219 self.assertEqual(B.reported, 2)
220 self.assertEqual(C.reported, 2)
James E. Blairb02a3bb2012-07-30 17:49:55 -0700221
222 def test_failed_changes(self):
223 "Test that a change behind a failed change is retested"
James E. Blaire2819012013-06-28 17:17:26 -0400224 self.worker.hold_jobs_in_build = True
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700225
James E. Blairb02a3bb2012-07-30 17:49:55 -0700226 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
227 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
James E. Blair8c803f82012-07-31 16:25:42 -0700228 A.addApproval('CRVW', 2)
229 B.addApproval('CRVW', 2)
James E. Blairb02a3bb2012-07-30 17:49:55 -0700230
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700231 self.worker.addFailTest('project-test1', A)
James E. Blairb02a3bb2012-07-30 17:49:55 -0700232
James E. Blaire2819012013-06-28 17:17:26 -0400233 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
234 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
James E. Blairb02a3bb2012-07-30 17:49:55 -0700235 self.waitUntilSettled()
James E. Blaire2819012013-06-28 17:17:26 -0400236
237 self.worker.release('.*-merge')
238 self.waitUntilSettled()
239
240 self.worker.hold_jobs_in_build = False
241 self.worker.release()
242
243 self.waitUntilSettled()
244 # It's certain that the merge job for change 2 will run, but
245 # the test1 and test2 jobs may or may not run.
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400246 self.assertTrue(len(self.history) > 6)
247 self.assertEqual(A.data['status'], 'NEW')
248 self.assertEqual(B.data['status'], 'MERGED')
249 self.assertEqual(A.reported, 2)
250 self.assertEqual(B.reported, 2)
James E. Blairb02a3bb2012-07-30 17:49:55 -0700251
252 def test_independent_queues(self):
253 "Test that changes end up in the right queues"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700254
255 self.worker.hold_jobs_in_build = True
Zhongyue Luo5d556072012-09-21 02:00:47 +0900256 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
James E. Blairb02a3bb2012-07-30 17:49:55 -0700257 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
258 C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
James E. Blair8c803f82012-07-31 16:25:42 -0700259 A.addApproval('CRVW', 2)
260 B.addApproval('CRVW', 2)
261 C.addApproval('CRVW', 2)
James E. Blairb02a3bb2012-07-30 17:49:55 -0700262
263 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
264 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
265 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
266
James E. Blairb02a3bb2012-07-30 17:49:55 -0700267 self.waitUntilSettled()
268
269 # There should be one merge job at the head of each queue running
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400270 self.assertEqual(len(self.builds), 2)
271 self.assertEqual(self.builds[0].name, 'project-merge')
272 self.assertTrue(self.job_has_changes(self.builds[0], A))
273 self.assertEqual(self.builds[1].name, 'project1-merge')
274 self.assertTrue(self.job_has_changes(self.builds[1], B))
James E. Blairb02a3bb2012-07-30 17:49:55 -0700275
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700276 # Release the current merge builds
277 self.worker.release('.*-merge')
James E. Blairb02a3bb2012-07-30 17:49:55 -0700278 self.waitUntilSettled()
279 # Release the merge job for project2 which is behind project1
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700280 self.worker.release('.*-merge')
James E. Blairb02a3bb2012-07-30 17:49:55 -0700281 self.waitUntilSettled()
282
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700283 # All the test builds should be running:
James E. Blairb02a3bb2012-07-30 17:49:55 -0700284 # project1 (3) + project2 (3) + project (2) = 8
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400285 self.assertEqual(len(self.builds), 8)
James E. Blairb02a3bb2012-07-30 17:49:55 -0700286
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700287 self.worker.release()
James E. Blairb02a3bb2012-07-30 17:49:55 -0700288 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400289 self.assertEqual(len(self.builds), 0)
James E. Blairb02a3bb2012-07-30 17:49:55 -0700290
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400291 self.assertEqual(len(self.history), 11)
292 self.assertEqual(A.data['status'], 'MERGED')
293 self.assertEqual(B.data['status'], 'MERGED')
294 self.assertEqual(C.data['status'], 'MERGED')
295 self.assertEqual(A.reported, 2)
296 self.assertEqual(B.reported, 2)
297 self.assertEqual(C.reported, 2)
James E. Blaird466dc42012-07-31 10:42:56 -0700298
299 def test_failed_change_at_head(self):
300 "Test that if a change at the head fails, jobs behind it are canceled"
James E. Blaird466dc42012-07-31 10:42:56 -0700301
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700302 self.worker.hold_jobs_in_build = True
James E. Blaird466dc42012-07-31 10:42:56 -0700303 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
304 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
305 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
James E. Blair8c803f82012-07-31 16:25:42 -0700306 A.addApproval('CRVW', 2)
307 B.addApproval('CRVW', 2)
308 C.addApproval('CRVW', 2)
James E. Blaird466dc42012-07-31 10:42:56 -0700309
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700310 self.worker.addFailTest('project-test1', A)
James E. Blaird466dc42012-07-31 10:42:56 -0700311
312 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
313 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
314 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
315
316 self.waitUntilSettled()
James E. Blaird466dc42012-07-31 10:42:56 -0700317
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400318 self.assertEqual(len(self.builds), 1)
319 self.assertEqual(self.builds[0].name, 'project-merge')
320 self.assertTrue(self.job_has_changes(self.builds[0], A))
James E. Blaird466dc42012-07-31 10:42:56 -0700321
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700322 self.worker.release('.*-merge')
James E. Blaird466dc42012-07-31 10:42:56 -0700323 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700324 self.worker.release('.*-merge')
James E. Blaird466dc42012-07-31 10:42:56 -0700325 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700326 self.worker.release('.*-merge')
James E. Blaird466dc42012-07-31 10:42:56 -0700327 self.waitUntilSettled()
328
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400329 self.assertEqual(len(self.builds), 6)
330 self.assertEqual(self.builds[0].name, 'project-test1')
331 self.assertEqual(self.builds[1].name, 'project-test2')
332 self.assertEqual(self.builds[2].name, 'project-test1')
333 self.assertEqual(self.builds[3].name, 'project-test2')
334 self.assertEqual(self.builds[4].name, 'project-test1')
335 self.assertEqual(self.builds[5].name, 'project-test2')
James E. Blaird466dc42012-07-31 10:42:56 -0700336
Monty Taylor6bef8ef2013-06-02 08:17:12 -0400337 self.release(self.builds[0])
James E. Blaird466dc42012-07-31 10:42:56 -0700338 self.waitUntilSettled()
339
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400340 # project-test2, project-merge for B
341 self.assertEqual(len(self.builds), 2)
342 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 4)
James E. Blaird466dc42012-07-31 10:42:56 -0700343
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700344 self.worker.hold_jobs_in_build = False
345 self.worker.release()
James E. Blaird466dc42012-07-31 10:42:56 -0700346 self.waitUntilSettled()
347
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400348 self.assertEqual(len(self.builds), 0)
349 self.assertEqual(len(self.history), 15)
350 self.assertEqual(A.data['status'], 'NEW')
351 self.assertEqual(B.data['status'], 'MERGED')
352 self.assertEqual(C.data['status'], 'MERGED')
353 self.assertEqual(A.reported, 2)
354 self.assertEqual(B.reported, 2)
355 self.assertEqual(C.reported, 2)
James E. Blaird466dc42012-07-31 10:42:56 -0700356
James E. Blair0aac4872013-08-23 14:02:38 -0700357 def test_failed_change_in_middle(self):
358 "Test a failed change in the middle of the queue"
359
360 self.worker.hold_jobs_in_build = True
361 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
362 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
363 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
364 A.addApproval('CRVW', 2)
365 B.addApproval('CRVW', 2)
366 C.addApproval('CRVW', 2)
367
368 self.worker.addFailTest('project-test1', B)
369
370 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
371 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
372 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
373
374 self.waitUntilSettled()
375
376 self.worker.release('.*-merge')
377 self.waitUntilSettled()
378 self.worker.release('.*-merge')
379 self.waitUntilSettled()
380 self.worker.release('.*-merge')
381 self.waitUntilSettled()
382
383 self.assertEqual(len(self.builds), 6)
384 self.assertEqual(self.builds[0].name, 'project-test1')
385 self.assertEqual(self.builds[1].name, 'project-test2')
386 self.assertEqual(self.builds[2].name, 'project-test1')
387 self.assertEqual(self.builds[3].name, 'project-test2')
388 self.assertEqual(self.builds[4].name, 'project-test1')
389 self.assertEqual(self.builds[5].name, 'project-test2')
390
391 self.release(self.builds[2])
392 self.waitUntilSettled()
393
James E. Blair972e3c72013-08-29 12:04:55 -0700394 # project-test1 and project-test2 for A
395 # project-test2 for B
396 # project-merge for C (without B)
397 self.assertEqual(len(self.builds), 4)
James E. Blair0aac4872013-08-23 14:02:38 -0700398 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 2)
399
James E. Blair972e3c72013-08-29 12:04:55 -0700400 self.worker.release('.*-merge')
401 self.waitUntilSettled()
402
403 # project-test1 and project-test2 for A
404 # project-test2 for B
405 # project-test1 and project-test2 for C
406 self.assertEqual(len(self.builds), 5)
407
James E. Blair0aac4872013-08-23 14:02:38 -0700408 items = self.sched.layout.pipelines['gate'].getAllItems()
409 builds = items[0].current_build_set.getBuilds()
410 self.assertEqual(self.countJobResults(builds, 'SUCCESS'), 1)
411 self.assertEqual(self.countJobResults(builds, None), 2)
412 builds = items[1].current_build_set.getBuilds()
413 self.assertEqual(self.countJobResults(builds, 'SUCCESS'), 1)
414 self.assertEqual(self.countJobResults(builds, 'FAILURE'), 1)
415 self.assertEqual(self.countJobResults(builds, None), 1)
416 builds = items[2].current_build_set.getBuilds()
417 self.assertEqual(self.countJobResults(builds, 'SUCCESS'), 1)
James E. Blair972e3c72013-08-29 12:04:55 -0700418 self.assertEqual(self.countJobResults(builds, None), 2)
James E. Blair0aac4872013-08-23 14:02:38 -0700419
420 self.worker.hold_jobs_in_build = False
421 self.worker.release()
422 self.waitUntilSettled()
423
424 self.assertEqual(len(self.builds), 0)
425 self.assertEqual(len(self.history), 12)
426 self.assertEqual(A.data['status'], 'MERGED')
427 self.assertEqual(B.data['status'], 'NEW')
428 self.assertEqual(C.data['status'], 'MERGED')
429 self.assertEqual(A.reported, 2)
430 self.assertEqual(B.reported, 2)
431 self.assertEqual(C.reported, 2)
432
James E. Blaird466dc42012-07-31 10:42:56 -0700433 def test_failed_change_at_head_with_queue(self):
434 "Test that if a change at the head fails, queued jobs are canceled"
James E. Blaird466dc42012-07-31 10:42:56 -0700435
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700436 self.gearman_server.hold_jobs_in_queue = True
James E. Blaird466dc42012-07-31 10:42:56 -0700437 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
438 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
439 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
James E. Blair8c803f82012-07-31 16:25:42 -0700440 A.addApproval('CRVW', 2)
441 B.addApproval('CRVW', 2)
442 C.addApproval('CRVW', 2)
James E. Blaird466dc42012-07-31 10:42:56 -0700443
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700444 self.worker.addFailTest('project-test1', A)
James E. Blaird466dc42012-07-31 10:42:56 -0700445
446 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
447 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
448 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
449
450 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -0700451 queue = self.gearman_server.getQueue()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400452 self.assertEqual(len(self.builds), 0)
453 self.assertEqual(len(queue), 1)
454 self.assertEqual(queue[0].name, 'build:project-merge')
455 self.assertTrue(self.job_has_changes(queue[0], A))
James E. Blaird466dc42012-07-31 10:42:56 -0700456
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700457 self.gearman_server.release('.*-merge')
James E. Blaird466dc42012-07-31 10:42:56 -0700458 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700459 self.gearman_server.release('.*-merge')
James E. Blaird466dc42012-07-31 10:42:56 -0700460 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700461 self.gearman_server.release('.*-merge')
James E. Blaird466dc42012-07-31 10:42:56 -0700462 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -0700463 queue = self.gearman_server.getQueue()
James E. Blaird466dc42012-07-31 10:42:56 -0700464
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400465 self.assertEqual(len(self.builds), 0)
466 self.assertEqual(len(queue), 6)
467 self.assertEqual(queue[0].name, 'build:project-test1')
468 self.assertEqual(queue[1].name, 'build:project-test2')
469 self.assertEqual(queue[2].name, 'build:project-test1')
470 self.assertEqual(queue[3].name, 'build:project-test2')
471 self.assertEqual(queue[4].name, 'build:project-test1')
472 self.assertEqual(queue[5].name, 'build:project-test2')
James E. Blaird466dc42012-07-31 10:42:56 -0700473
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700474 self.release(queue[0])
James E. Blaird466dc42012-07-31 10:42:56 -0700475 self.waitUntilSettled()
476
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400477 self.assertEqual(len(self.builds), 0)
James E. Blair701c5b42013-06-06 09:34:59 -0700478 queue = self.gearman_server.getQueue()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400479 self.assertEqual(len(queue), 2) # project-test2, project-merge for B
480 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 0)
James E. Blaird466dc42012-07-31 10:42:56 -0700481
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700482 self.gearman_server.hold_jobs_in_queue = False
483 self.gearman_server.release()
James E. Blaird466dc42012-07-31 10:42:56 -0700484 self.waitUntilSettled()
485
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400486 self.assertEqual(len(self.builds), 0)
487 self.assertEqual(len(self.history), 11)
488 self.assertEqual(A.data['status'], 'NEW')
489 self.assertEqual(B.data['status'], 'MERGED')
490 self.assertEqual(C.data['status'], 'MERGED')
491 self.assertEqual(A.reported, 2)
492 self.assertEqual(B.reported, 2)
493 self.assertEqual(C.reported, 2)
James E. Blair8c803f82012-07-31 16:25:42 -0700494
James E. Blairfef71632013-09-23 11:15:47 -0700495 def test_two_failed_changes_at_head(self):
496 "Test that changes are reparented correctly if 2 fail at head"
497
498 self.worker.hold_jobs_in_build = True
499 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
500 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
501 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
502 A.addApproval('CRVW', 2)
503 B.addApproval('CRVW', 2)
504 C.addApproval('CRVW', 2)
505
506 self.worker.addFailTest('project-test1', A)
507 self.worker.addFailTest('project-test1', B)
508
509 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
510 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
511 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
512 self.waitUntilSettled()
513
514 self.worker.release('.*-merge')
515 self.waitUntilSettled()
516 self.worker.release('.*-merge')
517 self.waitUntilSettled()
518 self.worker.release('.*-merge')
519 self.waitUntilSettled()
520
521 self.assertEqual(len(self.builds), 6)
522 self.assertEqual(self.builds[0].name, 'project-test1')
523 self.assertEqual(self.builds[1].name, 'project-test2')
524 self.assertEqual(self.builds[2].name, 'project-test1')
525 self.assertEqual(self.builds[3].name, 'project-test2')
526 self.assertEqual(self.builds[4].name, 'project-test1')
527 self.assertEqual(self.builds[5].name, 'project-test2')
528
529 self.assertTrue(self.job_has_changes(self.builds[0], A))
530 self.assertTrue(self.job_has_changes(self.builds[2], A))
531 self.assertTrue(self.job_has_changes(self.builds[2], B))
532 self.assertTrue(self.job_has_changes(self.builds[4], A))
533 self.assertTrue(self.job_has_changes(self.builds[4], B))
534 self.assertTrue(self.job_has_changes(self.builds[4], C))
535
536 # Fail change B first
537 self.release(self.builds[2])
538 self.waitUntilSettled()
539
540 # restart of C after B failure
541 self.worker.release('.*-merge')
542 self.waitUntilSettled()
543
544 self.assertEqual(len(self.builds), 5)
545 self.assertEqual(self.builds[0].name, 'project-test1')
546 self.assertEqual(self.builds[1].name, 'project-test2')
547 self.assertEqual(self.builds[2].name, 'project-test2')
548 self.assertEqual(self.builds[3].name, 'project-test1')
549 self.assertEqual(self.builds[4].name, 'project-test2')
550
551 self.assertTrue(self.job_has_changes(self.builds[1], A))
552 self.assertTrue(self.job_has_changes(self.builds[2], A))
553 self.assertTrue(self.job_has_changes(self.builds[2], B))
554 self.assertTrue(self.job_has_changes(self.builds[4], A))
555 self.assertFalse(self.job_has_changes(self.builds[4], B))
556 self.assertTrue(self.job_has_changes(self.builds[4], C))
557
558 # Finish running all passing jobs for change A
559 self.release(self.builds[1])
560 self.waitUntilSettled()
561 # Fail and report change A
562 self.release(self.builds[0])
563 self.waitUntilSettled()
564
565 # restart of B,C after A failure
566 self.worker.release('.*-merge')
567 self.waitUntilSettled()
568 self.worker.release('.*-merge')
569 self.waitUntilSettled()
570
571 self.assertEqual(len(self.builds), 4)
572 self.assertEqual(self.builds[0].name, 'project-test1') # B
573 self.assertEqual(self.builds[1].name, 'project-test2') # B
574 self.assertEqual(self.builds[2].name, 'project-test1') # C
575 self.assertEqual(self.builds[3].name, 'project-test2') # C
576
577 self.assertFalse(self.job_has_changes(self.builds[1], A))
578 self.assertTrue(self.job_has_changes(self.builds[1], B))
579 self.assertFalse(self.job_has_changes(self.builds[1], C))
580
581 self.assertFalse(self.job_has_changes(self.builds[2], A))
582 # After A failed and B and C restarted, B should be back in
583 # C's tests because it has not failed yet.
584 self.assertTrue(self.job_has_changes(self.builds[2], B))
585 self.assertTrue(self.job_has_changes(self.builds[2], C))
586
587 self.worker.hold_jobs_in_build = False
588 self.worker.release()
589 self.waitUntilSettled()
590
591 self.assertEqual(len(self.builds), 0)
592 self.assertEqual(len(self.history), 21)
593 self.assertEqual(A.data['status'], 'NEW')
594 self.assertEqual(B.data['status'], 'NEW')
595 self.assertEqual(C.data['status'], 'MERGED')
596 self.assertEqual(A.reported, 2)
597 self.assertEqual(B.reported, 2)
598 self.assertEqual(C.reported, 2)
599
James E. Blair8c803f82012-07-31 16:25:42 -0700600 def test_patch_order(self):
601 "Test that dependent patches are tested in the right order"
602 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
603 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
604 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
605 A.addApproval('CRVW', 2)
606 B.addApproval('CRVW', 2)
607 C.addApproval('CRVW', 2)
608
609 M2 = self.fake_gerrit.addFakeChange('org/project', 'master', 'M2')
610 M1 = self.fake_gerrit.addFakeChange('org/project', 'master', 'M1')
611 M2.setMerged()
612 M1.setMerged()
613
614 # C -> B -> A -> M1 -> M2
615 # M2 is here to make sure it is never queried. If it is, it
616 # means zuul is walking down the entire history of merged
617 # changes.
618
619 C.setDependsOn(B, 1)
620 B.setDependsOn(A, 1)
621 A.setDependsOn(M1, 1)
622 M1.setDependsOn(M2, 1)
623
624 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
625
626 self.waitUntilSettled()
627
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400628 self.assertEqual(A.data['status'], 'NEW')
629 self.assertEqual(B.data['status'], 'NEW')
630 self.assertEqual(C.data['status'], 'NEW')
James E. Blair8c803f82012-07-31 16:25:42 -0700631
632 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
633 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
634
635 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400636 self.assertEqual(M2.queried, 0)
637 self.assertEqual(A.data['status'], 'MERGED')
638 self.assertEqual(B.data['status'], 'MERGED')
639 self.assertEqual(C.data['status'], 'MERGED')
640 self.assertEqual(A.reported, 2)
641 self.assertEqual(B.reported, 2)
642 self.assertEqual(C.reported, 2)
James E. Blair8c803f82012-07-31 16:25:42 -0700643
James E. Blair063672f2015-01-29 13:09:12 -0800644 def test_needed_changes_enqueue(self):
645 "Test that a needed change is enqueued ahead"
646 # A Given a git tree like this, if we enqueue
647 # / \ change C, we should walk up and down the tree
648 # B G and enqueue changes in the order ABCDEFG.
649 # /|\ This is also the order that you would get if
650 # *C E F you enqueued changes in the order ABCDEFG, so
651 # / the ordering is stable across re-enqueue events.
652 # D
653
654 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
655 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
656 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
657 D = self.fake_gerrit.addFakeChange('org/project', 'master', 'D')
658 E = self.fake_gerrit.addFakeChange('org/project', 'master', 'E')
659 F = self.fake_gerrit.addFakeChange('org/project', 'master', 'F')
660 G = self.fake_gerrit.addFakeChange('org/project', 'master', 'G')
661 B.setDependsOn(A, 1)
662 C.setDependsOn(B, 1)
663 D.setDependsOn(C, 1)
664 E.setDependsOn(B, 1)
665 F.setDependsOn(B, 1)
666 G.setDependsOn(A, 1)
667
668 A.addApproval('CRVW', 2)
669 B.addApproval('CRVW', 2)
670 C.addApproval('CRVW', 2)
671 D.addApproval('CRVW', 2)
672 E.addApproval('CRVW', 2)
673 F.addApproval('CRVW', 2)
674 G.addApproval('CRVW', 2)
675 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
676
677 self.waitUntilSettled()
678
679 self.assertEqual(A.data['status'], 'NEW')
680 self.assertEqual(B.data['status'], 'NEW')
681 self.assertEqual(C.data['status'], 'NEW')
682 self.assertEqual(D.data['status'], 'NEW')
683 self.assertEqual(E.data['status'], 'NEW')
684 self.assertEqual(F.data['status'], 'NEW')
685 self.assertEqual(G.data['status'], 'NEW')
686
687 # We're about to add approvals to changes without adding the
688 # triggering events to Zuul, so that we can be sure that it is
689 # enqueing the changes based on dependencies, not because of
690 # triggering events. Since it will have the changes cached
691 # already (without approvals), we need to clear the cache
692 # first.
693 source = self.sched.layout.pipelines['gate'].source
694 source.maintainCache([])
695
696 self.worker.hold_jobs_in_build = True
697 A.addApproval('APRV', 1)
698 B.addApproval('APRV', 1)
699 D.addApproval('APRV', 1)
700 E.addApproval('APRV', 1)
701 F.addApproval('APRV', 1)
702 G.addApproval('APRV', 1)
703 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
704
705 for x in range(8):
706 self.worker.release('.*-merge')
707 self.waitUntilSettled()
708 self.worker.hold_jobs_in_build = False
709 self.worker.release()
710 self.waitUntilSettled()
711
712 self.assertEqual(A.data['status'], 'MERGED')
713 self.assertEqual(B.data['status'], 'MERGED')
714 self.assertEqual(C.data['status'], 'MERGED')
715 self.assertEqual(D.data['status'], 'MERGED')
716 self.assertEqual(E.data['status'], 'MERGED')
717 self.assertEqual(F.data['status'], 'MERGED')
718 self.assertEqual(G.data['status'], 'MERGED')
719 self.assertEqual(A.reported, 2)
720 self.assertEqual(B.reported, 2)
721 self.assertEqual(C.reported, 2)
722 self.assertEqual(D.reported, 2)
723 self.assertEqual(E.reported, 2)
724 self.assertEqual(F.reported, 2)
725 self.assertEqual(G.reported, 2)
726 self.assertEqual(self.history[6].changes,
727 '1,1 2,1 3,1 4,1 5,1 6,1 7,1')
728
James E. Blair0e933c52013-07-11 10:18:52 -0700729 def test_trigger_cache(self):
730 "Test that the trigger cache operates correctly"
731 self.worker.hold_jobs_in_build = True
732
733 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
734 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
735 X = self.fake_gerrit.addFakeChange('org/project', 'master', 'X')
736 A.addApproval('CRVW', 2)
737 B.addApproval('CRVW', 2)
738
739 M1 = self.fake_gerrit.addFakeChange('org/project', 'master', 'M1')
740 M1.setMerged()
741
742 B.setDependsOn(A, 1)
743 A.setDependsOn(M1, 1)
744
745 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
746 self.fake_gerrit.addEvent(X.getPatchsetCreatedEvent(1))
747
748 self.waitUntilSettled()
749
750 for build in self.builds:
751 if build.parameters['ZUUL_PIPELINE'] == 'check':
752 build.release()
753 self.waitUntilSettled()
754 for build in self.builds:
755 if build.parameters['ZUUL_PIPELINE'] == 'check':
756 build.release()
757 self.waitUntilSettled()
758
759 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
760 self.waitUntilSettled()
761
Antoine Mussof0506fa2014-06-03 15:03:38 +0200762 self.log.debug("len %s" % self.gerrit._change_cache.keys())
James E. Blair0e933c52013-07-11 10:18:52 -0700763 # there should still be changes in the cache
James E. Blair6c358e72013-07-29 17:06:47 -0700764 self.assertNotEqual(len(self.gerrit._change_cache.keys()), 0)
James E. Blair0e933c52013-07-11 10:18:52 -0700765
766 self.worker.hold_jobs_in_build = False
767 self.worker.release()
768 self.waitUntilSettled()
769
770 self.assertEqual(A.data['status'], 'MERGED')
771 self.assertEqual(B.data['status'], 'MERGED')
772 self.assertEqual(A.queried, 2) # Initial and isMerged
773 self.assertEqual(B.queried, 3) # Initial A, refresh from B, isMerged
774
James E. Blair8c803f82012-07-31 16:25:42 -0700775 def test_can_merge(self):
James E. Blair4886cc12012-07-18 15:39:41 -0700776 "Test whether a change is ready to merge"
James E. Blair8c803f82012-07-31 16:25:42 -0700777 # TODO: move to test_gerrit (this is a unit test!)
778 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
James E. Blairc0dedf82014-08-06 09:37:52 -0700779 source = self.sched.layout.pipelines['gate'].source
780 a = source._getChange(1, 2)
James E. Blaireff88162013-07-01 12:44:14 -0400781 mgr = self.sched.layout.pipelines['gate'].manager
James E. Blairc0dedf82014-08-06 09:37:52 -0700782 self.assertFalse(source.canMerge(a, mgr.getSubmitAllowNeeds()))
James E. Blair8c803f82012-07-31 16:25:42 -0700783
784 A.addApproval('CRVW', 2)
James E. Blairc0dedf82014-08-06 09:37:52 -0700785 a = source._getChange(1, 2, refresh=True)
786 self.assertFalse(source.canMerge(a, mgr.getSubmitAllowNeeds()))
James E. Blair8c803f82012-07-31 16:25:42 -0700787
788 A.addApproval('APRV', 1)
James E. Blairc0dedf82014-08-06 09:37:52 -0700789 a = source._getChange(1, 2, refresh=True)
790 self.assertTrue(source.canMerge(a, mgr.getSubmitAllowNeeds()))
791 source.maintainCache([])
James E. Blair4886cc12012-07-18 15:39:41 -0700792
793 def test_build_configuration(self):
794 "Test that zuul merges the right commits for testing"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700795
796 self.gearman_server.hold_jobs_in_queue = True
James E. Blair4886cc12012-07-18 15:39:41 -0700797 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
798 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
799 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
800 A.addApproval('CRVW', 2)
801 B.addApproval('CRVW', 2)
802 C.addApproval('CRVW', 2)
803 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
804 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
805 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
806 self.waitUntilSettled()
807
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700808 self.gearman_server.release('.*-merge')
James E. Blair4886cc12012-07-18 15:39:41 -0700809 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700810 self.gearman_server.release('.*-merge')
James E. Blair4886cc12012-07-18 15:39:41 -0700811 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700812 self.gearman_server.release('.*-merge')
James E. Blair4886cc12012-07-18 15:39:41 -0700813 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -0700814 queue = self.gearman_server.getQueue()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700815 ref = self.getParameter(queue[-1], 'ZUUL_REF')
816 self.gearman_server.hold_jobs_in_queue = False
817 self.gearman_server.release()
James E. Blair973721f2012-08-15 10:19:43 -0700818 self.waitUntilSettled()
James E. Blair4886cc12012-07-18 15:39:41 -0700819
Monty Taylorbc758832013-06-17 17:22:42 -0400820 path = os.path.join(self.git_root, "org/project")
James E. Blair4886cc12012-07-18 15:39:41 -0700821 repo = git.Repo(path)
822 repo_messages = [c.message.strip() for c in repo.iter_commits(ref)]
823 repo_messages.reverse()
James E. Blair4886cc12012-07-18 15:39:41 -0700824 correct_messages = ['initial commit', 'A-1', 'B-1', 'C-1']
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400825 self.assertEqual(repo_messages, correct_messages)
James E. Blair973721f2012-08-15 10:19:43 -0700826
827 def test_build_configuration_conflict(self):
828 "Test that merge conflicts are handled"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700829
830 self.gearman_server.hold_jobs_in_queue = True
James E. Blair6736beb2013-07-11 15:18:15 -0700831 A = self.fake_gerrit.addFakeChange('org/conflict-project',
832 'master', 'A')
James E. Blair973721f2012-08-15 10:19:43 -0700833 A.addPatchset(['conflict'])
James E. Blair6736beb2013-07-11 15:18:15 -0700834 B = self.fake_gerrit.addFakeChange('org/conflict-project',
835 'master', 'B')
James E. Blair973721f2012-08-15 10:19:43 -0700836 B.addPatchset(['conflict'])
James E. Blair6736beb2013-07-11 15:18:15 -0700837 C = self.fake_gerrit.addFakeChange('org/conflict-project',
838 'master', 'C')
James E. Blair973721f2012-08-15 10:19:43 -0700839 A.addApproval('CRVW', 2)
840 B.addApproval('CRVW', 2)
841 C.addApproval('CRVW', 2)
842 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
843 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
844 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
845 self.waitUntilSettled()
846
James E. Blair6736beb2013-07-11 15:18:15 -0700847 self.assertEqual(A.reported, 1)
848 self.assertEqual(B.reported, 1)
849 self.assertEqual(C.reported, 1)
850
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700851 self.gearman_server.release('.*-merge')
James E. Blair973721f2012-08-15 10:19:43 -0700852 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700853 self.gearman_server.release('.*-merge')
James E. Blair973721f2012-08-15 10:19:43 -0700854 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700855 self.gearman_server.release('.*-merge')
James E. Blair973721f2012-08-15 10:19:43 -0700856 self.waitUntilSettled()
James E. Blair972e3c72013-08-29 12:04:55 -0700857
858 self.assertEqual(len(self.history), 2) # A and C merge jobs
859
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700860 self.gearman_server.hold_jobs_in_queue = False
861 self.gearman_server.release()
James E. Blair973721f2012-08-15 10:19:43 -0700862 self.waitUntilSettled()
863
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400864 self.assertEqual(A.data['status'], 'MERGED')
865 self.assertEqual(B.data['status'], 'NEW')
866 self.assertEqual(C.data['status'], 'MERGED')
867 self.assertEqual(A.reported, 2)
868 self.assertEqual(B.reported, 2)
869 self.assertEqual(C.reported, 2)
James E. Blair972e3c72013-08-29 12:04:55 -0700870 self.assertEqual(len(self.history), 6)
James E. Blair6736beb2013-07-11 15:18:15 -0700871
James E. Blairdaabed22012-08-15 15:38:57 -0700872 def test_post(self):
873 "Test that post jobs run"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700874
Zhongyue Luo5d556072012-09-21 02:00:47 +0900875 e = {
876 "type": "ref-updated",
877 "submitter": {
878 "name": "User Name",
879 },
880 "refUpdate": {
881 "oldRev": "90f173846e3af9154517b88543ffbd1691f31366",
882 "newRev": "d479a0bfcb34da57a31adb2a595c0cf687812543",
883 "refName": "master",
884 "project": "org/project",
885 }
886 }
James E. Blairdaabed22012-08-15 15:38:57 -0700887 self.fake_gerrit.addEvent(e)
888 self.waitUntilSettled()
889
Monty Taylor6bef8ef2013-06-02 08:17:12 -0400890 job_names = [x.name for x in self.history]
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400891 self.assertEqual(len(self.history), 1)
892 self.assertIn('project-post', job_names)
James E. Blairc6294a52012-08-17 10:19:48 -0700893
K Jonathan Harkerf95e7232015-04-29 13:33:16 -0700894 def test_post_ignore_deletes(self):
895 "Test that deleting refs does not trigger post jobs"
896
897 e = {
898 "type": "ref-updated",
899 "submitter": {
900 "name": "User Name",
901 },
902 "refUpdate": {
903 "oldRev": "90f173846e3af9154517b88543ffbd1691f31366",
904 "newRev": "0000000000000000000000000000000000000000",
905 "refName": "master",
906 "project": "org/project",
907 }
908 }
909 self.fake_gerrit.addEvent(e)
910 self.waitUntilSettled()
911
912 job_names = [x.name for x in self.history]
913 self.assertEqual(len(self.history), 0)
914 self.assertNotIn('project-post', job_names)
915
916 def test_post_ignore_deletes_negative(self):
917 "Test that deleting refs does trigger post jobs"
918
919 self.config.set('zuul', 'layout_config',
920 'tests/fixtures/layout-dont-ignore-deletes.yaml')
921 self.sched.reconfigure(self.config)
922
923 e = {
924 "type": "ref-updated",
925 "submitter": {
926 "name": "User Name",
927 },
928 "refUpdate": {
929 "oldRev": "90f173846e3af9154517b88543ffbd1691f31366",
930 "newRev": "0000000000000000000000000000000000000000",
931 "refName": "master",
932 "project": "org/project",
933 }
934 }
935 self.fake_gerrit.addEvent(e)
936 self.waitUntilSettled()
937
938 job_names = [x.name for x in self.history]
939 self.assertEqual(len(self.history), 1)
940 self.assertIn('project-post', job_names)
941
James E. Blairc6294a52012-08-17 10:19:48 -0700942 def test_build_configuration_branch(self):
943 "Test that the right commits are on alternate branches"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700944
945 self.gearman_server.hold_jobs_in_queue = True
James E. Blairc6294a52012-08-17 10:19:48 -0700946 A = self.fake_gerrit.addFakeChange('org/project', 'mp', 'A')
947 B = self.fake_gerrit.addFakeChange('org/project', 'mp', 'B')
948 C = self.fake_gerrit.addFakeChange('org/project', 'mp', 'C')
949 A.addApproval('CRVW', 2)
950 B.addApproval('CRVW', 2)
951 C.addApproval('CRVW', 2)
952 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
953 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
954 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
955 self.waitUntilSettled()
956
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700957 self.gearman_server.release('.*-merge')
James E. Blairc6294a52012-08-17 10:19:48 -0700958 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700959 self.gearman_server.release('.*-merge')
James E. Blairc6294a52012-08-17 10:19:48 -0700960 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700961 self.gearman_server.release('.*-merge')
James E. Blairc6294a52012-08-17 10:19:48 -0700962 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -0700963 queue = self.gearman_server.getQueue()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700964 ref = self.getParameter(queue[-1], 'ZUUL_REF')
965 self.gearman_server.hold_jobs_in_queue = False
966 self.gearman_server.release()
James E. Blairc6294a52012-08-17 10:19:48 -0700967 self.waitUntilSettled()
968
Monty Taylorbc758832013-06-17 17:22:42 -0400969 path = os.path.join(self.git_root, "org/project")
James E. Blairc6294a52012-08-17 10:19:48 -0700970 repo = git.Repo(path)
971 repo_messages = [c.message.strip() for c in repo.iter_commits(ref)]
972 repo_messages.reverse()
James E. Blairc6294a52012-08-17 10:19:48 -0700973 correct_messages = ['initial commit', 'mp commit', 'A-1', 'B-1', 'C-1']
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400974 self.assertEqual(repo_messages, correct_messages)
James E. Blairc6294a52012-08-17 10:19:48 -0700975
976 def test_build_configuration_branch_interaction(self):
977 "Test that switching between branches works"
978 self.test_build_configuration()
979 self.test_build_configuration_branch()
980 # C has been merged, undo that
Monty Taylorbc758832013-06-17 17:22:42 -0400981 path = os.path.join(self.upstream_root, "org/project")
James E. Blairc6294a52012-08-17 10:19:48 -0700982 repo = git.Repo(path)
983 repo.heads.master.commit = repo.commit('init')
984 self.test_build_configuration()
985
986 def test_build_configuration_multi_branch(self):
987 "Test that dependent changes on multiple branches are merged"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700988
989 self.gearman_server.hold_jobs_in_queue = True
James E. Blairc6294a52012-08-17 10:19:48 -0700990 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
991 B = self.fake_gerrit.addFakeChange('org/project', 'mp', 'B')
992 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
993 A.addApproval('CRVW', 2)
994 B.addApproval('CRVW', 2)
995 C.addApproval('CRVW', 2)
996 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
997 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
998 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
999 self.waitUntilSettled()
James E. Blairbb1fe502014-03-04 10:15:06 -08001000 queue = self.gearman_server.getQueue()
1001 job_A = None
1002 for job in queue:
1003 if 'project-merge' in job.name:
1004 job_A = job
1005 ref_A = self.getParameter(job_A, 'ZUUL_REF')
1006 commit_A = self.getParameter(job_A, 'ZUUL_COMMIT')
1007 self.log.debug("Got Zuul ref for change A: %s" % ref_A)
1008 self.log.debug("Got Zuul commit for change A: %s" % commit_A)
James E. Blairc6294a52012-08-17 10:19:48 -07001009
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001010 self.gearman_server.release('.*-merge')
James E. Blairc6294a52012-08-17 10:19:48 -07001011 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -07001012 queue = self.gearman_server.getQueue()
James E. Blaird320d7e2013-07-30 16:36:20 -07001013 job_B = None
1014 for job in queue:
1015 if 'project-merge' in job.name:
1016 job_B = job
1017 ref_B = self.getParameter(job_B, 'ZUUL_REF')
James E. Blairbb1fe502014-03-04 10:15:06 -08001018 commit_B = self.getParameter(job_B, 'ZUUL_COMMIT')
James E. Blairf750aa02013-07-15 14:11:24 -07001019 self.log.debug("Got Zuul ref for change B: %s" % ref_B)
James E. Blairbb1fe502014-03-04 10:15:06 -08001020 self.log.debug("Got Zuul commit for change B: %s" % commit_B)
1021
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001022 self.gearman_server.release('.*-merge')
James E. Blairc6294a52012-08-17 10:19:48 -07001023 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -07001024 queue = self.gearman_server.getQueue()
James E. Blaird320d7e2013-07-30 16:36:20 -07001025 for job in queue:
1026 if 'project-merge' in job.name:
1027 job_C = job
1028 ref_C = self.getParameter(job_C, 'ZUUL_REF')
James E. Blairbb1fe502014-03-04 10:15:06 -08001029 commit_C = self.getParameter(job_C, 'ZUUL_COMMIT')
James E. Blairf750aa02013-07-15 14:11:24 -07001030 self.log.debug("Got Zuul ref for change C: %s" % ref_C)
James E. Blairbb1fe502014-03-04 10:15:06 -08001031 self.log.debug("Got Zuul commit for change C: %s" % commit_C)
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001032 self.gearman_server.hold_jobs_in_queue = False
1033 self.gearman_server.release()
James E. Blairc6294a52012-08-17 10:19:48 -07001034 self.waitUntilSettled()
1035
Monty Taylorbc758832013-06-17 17:22:42 -04001036 path = os.path.join(self.git_root, "org/project")
James E. Blairc6294a52012-08-17 10:19:48 -07001037 repo = git.Repo(path)
1038
1039 repo_messages = [c.message.strip()
James E. Blairf750aa02013-07-15 14:11:24 -07001040 for c in repo.iter_commits(ref_C)]
James E. Blairbb1fe502014-03-04 10:15:06 -08001041 repo_shas = [c.hexsha for c in repo.iter_commits(ref_C)]
James E. Blairc6294a52012-08-17 10:19:48 -07001042 repo_messages.reverse()
James E. Blairc6294a52012-08-17 10:19:48 -07001043 correct_messages = ['initial commit', 'A-1', 'C-1']
James E. Blairbb1fe502014-03-04 10:15:06 -08001044 # Ensure the right commits are in the history for this ref
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001045 self.assertEqual(repo_messages, correct_messages)
James E. Blairbb1fe502014-03-04 10:15:06 -08001046 # Ensure ZUUL_REF -> ZUUL_COMMIT
1047 self.assertEqual(repo_shas[0], commit_C)
James E. Blairc6294a52012-08-17 10:19:48 -07001048
1049 repo_messages = [c.message.strip()
James E. Blairf750aa02013-07-15 14:11:24 -07001050 for c in repo.iter_commits(ref_B)]
James E. Blairbb1fe502014-03-04 10:15:06 -08001051 repo_shas = [c.hexsha for c in repo.iter_commits(ref_B)]
James E. Blairc6294a52012-08-17 10:19:48 -07001052 repo_messages.reverse()
James E. Blairc6294a52012-08-17 10:19:48 -07001053 correct_messages = ['initial commit', 'mp commit', 'B-1']
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001054 self.assertEqual(repo_messages, correct_messages)
James E. Blairbb1fe502014-03-04 10:15:06 -08001055 self.assertEqual(repo_shas[0], commit_B)
1056
1057 repo_messages = [c.message.strip()
1058 for c in repo.iter_commits(ref_A)]
1059 repo_shas = [c.hexsha for c in repo.iter_commits(ref_A)]
1060 repo_messages.reverse()
1061 correct_messages = ['initial commit', 'A-1']
1062 self.assertEqual(repo_messages, correct_messages)
1063 self.assertEqual(repo_shas[0], commit_A)
1064
1065 self.assertNotEqual(ref_A, ref_B, ref_C)
1066 self.assertNotEqual(commit_A, commit_B, commit_C)
James E. Blair7f71c802012-08-22 13:04:32 -07001067
1068 def test_one_job_project(self):
1069 "Test that queueing works with one job"
1070 A = self.fake_gerrit.addFakeChange('org/one-job-project',
1071 'master', 'A')
1072 B = self.fake_gerrit.addFakeChange('org/one-job-project',
1073 'master', 'B')
1074 A.addApproval('CRVW', 2)
1075 B.addApproval('CRVW', 2)
1076 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1077 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1078 self.waitUntilSettled()
1079
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001080 self.assertEqual(A.data['status'], 'MERGED')
1081 self.assertEqual(A.reported, 2)
1082 self.assertEqual(B.data['status'], 'MERGED')
1083 self.assertEqual(B.reported, 2)
James E. Blaircaec0c52012-08-22 14:52:22 -07001084
Antoine Musso80edd5a2013-02-13 15:37:53 +01001085 def test_job_from_templates_launched(self):
1086 "Test whether a job generated via a template can be launched"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001087
Antoine Musso80edd5a2013-02-13 15:37:53 +01001088 A = self.fake_gerrit.addFakeChange(
1089 'org/templated-project', 'master', 'A')
1090 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1091 self.waitUntilSettled()
Antoine Musso80edd5a2013-02-13 15:37:53 +01001092
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001093 self.assertEqual(self.getJobFromHistory('project-test1').result,
1094 'SUCCESS')
1095 self.assertEqual(self.getJobFromHistory('project-test2').result,
1096 'SUCCESS')
Antoine Musso80edd5a2013-02-13 15:37:53 +01001097
James E. Blair3e98c022013-12-16 15:25:38 -08001098 def test_layered_templates(self):
1099 "Test whether a job generated via a template can be launched"
1100
1101 A = self.fake_gerrit.addFakeChange(
1102 'org/layered-project', 'master', 'A')
1103 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1104 self.waitUntilSettled()
1105
1106 self.assertEqual(self.getJobFromHistory('project-test1').result,
1107 'SUCCESS')
1108 self.assertEqual(self.getJobFromHistory('project-test2').result,
1109 'SUCCESS')
James E. Blairaea6cf62013-12-16 15:38:12 -08001110 self.assertEqual(self.getJobFromHistory('layered-project-test3'
1111 ).result, 'SUCCESS')
1112 self.assertEqual(self.getJobFromHistory('layered-project-test4'
1113 ).result, 'SUCCESS')
James E. Blair12a92b12014-03-26 11:54:53 -07001114 self.assertEqual(self.getJobFromHistory('layered-project-foo-test5'
1115 ).result, 'SUCCESS')
James E. Blair3e98c022013-12-16 15:25:38 -08001116 self.assertEqual(self.getJobFromHistory('project-test6').result,
1117 'SUCCESS')
1118
James E. Blaircaec0c52012-08-22 14:52:22 -07001119 def test_dependent_changes_dequeue(self):
1120 "Test that dependent patches are not needlessly tested"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001121
James E. Blaircaec0c52012-08-22 14:52:22 -07001122 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1123 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1124 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1125 A.addApproval('CRVW', 2)
1126 B.addApproval('CRVW', 2)
1127 C.addApproval('CRVW', 2)
1128
1129 M1 = self.fake_gerrit.addFakeChange('org/project', 'master', 'M1')
1130 M1.setMerged()
1131
1132 # C -> B -> A -> M1
1133
1134 C.setDependsOn(B, 1)
1135 B.setDependsOn(A, 1)
1136 A.setDependsOn(M1, 1)
1137
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001138 self.worker.addFailTest('project-merge', A)
James E. Blaircaec0c52012-08-22 14:52:22 -07001139
1140 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1141 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1142 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1143
1144 self.waitUntilSettled()
1145
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001146 self.assertEqual(A.data['status'], 'NEW')
1147 self.assertEqual(A.reported, 2)
1148 self.assertEqual(B.data['status'], 'NEW')
1149 self.assertEqual(B.reported, 2)
1150 self.assertEqual(C.data['status'], 'NEW')
1151 self.assertEqual(C.reported, 2)
1152 self.assertEqual(len(self.history), 1)
James E. Blairec590122012-08-22 15:19:31 -07001153
James E. Blair972e3c72013-08-29 12:04:55 -07001154 def test_failing_dependent_changes(self):
1155 "Test that failing dependent patches are taken out of stream"
1156 self.worker.hold_jobs_in_build = True
1157 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1158 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1159 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1160 D = self.fake_gerrit.addFakeChange('org/project', 'master', 'D')
1161 E = self.fake_gerrit.addFakeChange('org/project', 'master', 'E')
1162 A.addApproval('CRVW', 2)
1163 B.addApproval('CRVW', 2)
1164 C.addApproval('CRVW', 2)
1165 D.addApproval('CRVW', 2)
1166 E.addApproval('CRVW', 2)
1167
1168 # E, D -> C -> B, A
1169
1170 D.setDependsOn(C, 1)
1171 C.setDependsOn(B, 1)
1172
1173 self.worker.addFailTest('project-test1', B)
1174
1175 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1176 self.fake_gerrit.addEvent(D.addApproval('APRV', 1))
1177 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1178 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1179 self.fake_gerrit.addEvent(E.addApproval('APRV', 1))
1180
1181 self.waitUntilSettled()
1182 self.worker.release('.*-merge')
1183 self.waitUntilSettled()
1184 self.worker.release('.*-merge')
1185 self.waitUntilSettled()
1186 self.worker.release('.*-merge')
1187 self.waitUntilSettled()
1188 self.worker.release('.*-merge')
1189 self.waitUntilSettled()
1190 self.worker.release('.*-merge')
1191 self.waitUntilSettled()
1192
1193 self.worker.hold_jobs_in_build = False
1194 for build in self.builds:
1195 if build.parameters['ZUUL_CHANGE'] != '1':
1196 build.release()
1197 self.waitUntilSettled()
1198
1199 self.worker.release()
1200 self.waitUntilSettled()
1201
1202 self.assertEqual(A.data['status'], 'MERGED')
1203 self.assertEqual(A.reported, 2)
Jeremy Stanley10837132014-08-02 16:10:56 +00001204 self.assertIn('Build succeeded', A.messages[1])
James E. Blair972e3c72013-08-29 12:04:55 -07001205 self.assertEqual(B.data['status'], 'NEW')
1206 self.assertEqual(B.reported, 2)
Jeremy Stanley10837132014-08-02 16:10:56 +00001207 self.assertIn('Build failed', B.messages[1])
James E. Blair972e3c72013-08-29 12:04:55 -07001208 self.assertEqual(C.data['status'], 'NEW')
1209 self.assertEqual(C.reported, 2)
Jeremy Stanley10837132014-08-02 16:10:56 +00001210 self.assertIn('depends on a change', C.messages[1])
James E. Blair972e3c72013-08-29 12:04:55 -07001211 self.assertEqual(D.data['status'], 'NEW')
1212 self.assertEqual(D.reported, 2)
Jeremy Stanley10837132014-08-02 16:10:56 +00001213 self.assertIn('depends on a change', D.messages[1])
James E. Blair972e3c72013-08-29 12:04:55 -07001214 self.assertEqual(E.data['status'], 'MERGED')
1215 self.assertEqual(E.reported, 2)
Jeremy Stanley10837132014-08-02 16:10:56 +00001216 self.assertIn('Build succeeded', E.messages[1])
James E. Blair972e3c72013-08-29 12:04:55 -07001217 self.assertEqual(len(self.history), 18)
1218
James E. Blairec590122012-08-22 15:19:31 -07001219 def test_head_is_dequeued_once(self):
James E. Blair2fa50962013-01-30 21:50:41 -08001220 "Test that if a change at the head fails it is dequeued only once"
James E. Blairec590122012-08-22 15:19:31 -07001221 # If it's dequeued more than once, we should see extra
1222 # aborted jobs.
James E. Blairec590122012-08-22 15:19:31 -07001223
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001224 self.worker.hold_jobs_in_build = True
James E. Blairec590122012-08-22 15:19:31 -07001225 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
1226 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
1227 C = self.fake_gerrit.addFakeChange('org/project1', 'master', 'C')
1228 A.addApproval('CRVW', 2)
1229 B.addApproval('CRVW', 2)
1230 C.addApproval('CRVW', 2)
1231
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001232 self.worker.addFailTest('project1-test1', A)
1233 self.worker.addFailTest('project1-test2', A)
1234 self.worker.addFailTest('project1-project2-integration', A)
James E. Blairec590122012-08-22 15:19:31 -07001235
1236 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1237 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1238 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1239
1240 self.waitUntilSettled()
James E. Blairec590122012-08-22 15:19:31 -07001241
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001242 self.assertEqual(len(self.builds), 1)
1243 self.assertEqual(self.builds[0].name, 'project1-merge')
1244 self.assertTrue(self.job_has_changes(self.builds[0], A))
James E. Blairec590122012-08-22 15:19:31 -07001245
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001246 self.worker.release('.*-merge')
James E. Blairec590122012-08-22 15:19:31 -07001247 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001248 self.worker.release('.*-merge')
James E. Blairec590122012-08-22 15:19:31 -07001249 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001250 self.worker.release('.*-merge')
James E. Blairec590122012-08-22 15:19:31 -07001251 self.waitUntilSettled()
1252
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001253 self.assertEqual(len(self.builds), 9)
1254 self.assertEqual(self.builds[0].name, 'project1-test1')
1255 self.assertEqual(self.builds[1].name, 'project1-test2')
1256 self.assertEqual(self.builds[2].name, 'project1-project2-integration')
1257 self.assertEqual(self.builds[3].name, 'project1-test1')
1258 self.assertEqual(self.builds[4].name, 'project1-test2')
1259 self.assertEqual(self.builds[5].name, 'project1-project2-integration')
1260 self.assertEqual(self.builds[6].name, 'project1-test1')
1261 self.assertEqual(self.builds[7].name, 'project1-test2')
1262 self.assertEqual(self.builds[8].name, 'project1-project2-integration')
James E. Blairec590122012-08-22 15:19:31 -07001263
Monty Taylor6bef8ef2013-06-02 08:17:12 -04001264 self.release(self.builds[0])
James E. Blairec590122012-08-22 15:19:31 -07001265 self.waitUntilSettled()
1266
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001267 self.assertEqual(len(self.builds), 3) # test2,integration, merge for B
1268 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 6)
James E. Blairec590122012-08-22 15:19:31 -07001269
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001270 self.worker.hold_jobs_in_build = False
1271 self.worker.release()
James E. Blairec590122012-08-22 15:19:31 -07001272 self.waitUntilSettled()
1273
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001274 self.assertEqual(len(self.builds), 0)
1275 self.assertEqual(len(self.history), 20)
James E. Blaircaec0c52012-08-22 14:52:22 -07001276
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001277 self.assertEqual(A.data['status'], 'NEW')
1278 self.assertEqual(B.data['status'], 'MERGED')
1279 self.assertEqual(C.data['status'], 'MERGED')
1280 self.assertEqual(A.reported, 2)
1281 self.assertEqual(B.reported, 2)
1282 self.assertEqual(C.reported, 2)
James E. Blair4ec821f2012-08-23 15:28:28 -07001283
1284 def test_nonvoting_job(self):
1285 "Test that non-voting jobs don't vote."
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001286
James E. Blair4ec821f2012-08-23 15:28:28 -07001287 A = self.fake_gerrit.addFakeChange('org/nonvoting-project',
1288 'master', 'A')
1289 A.addApproval('CRVW', 2)
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001290 self.worker.addFailTest('nonvoting-project-test2', A)
James E. Blair4ec821f2012-08-23 15:28:28 -07001291 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1292
1293 self.waitUntilSettled()
James E. Blair4ec821f2012-08-23 15:28:28 -07001294
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001295 self.assertEqual(A.data['status'], 'MERGED')
1296 self.assertEqual(A.reported, 2)
1297 self.assertEqual(
1298 self.getJobFromHistory('nonvoting-project-merge').result,
1299 'SUCCESS')
1300 self.assertEqual(
1301 self.getJobFromHistory('nonvoting-project-test1').result,
1302 'SUCCESS')
1303 self.assertEqual(
1304 self.getJobFromHistory('nonvoting-project-test2').result,
1305 'FAILURE')
James E. Blaire0487072012-08-29 17:38:31 -07001306
1307 def test_check_queue_success(self):
1308 "Test successful check queue jobs."
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001309
James E. Blaire0487072012-08-29 17:38:31 -07001310 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1311 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1312
1313 self.waitUntilSettled()
James E. Blaire0487072012-08-29 17:38:31 -07001314
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001315 self.assertEqual(A.data['status'], 'NEW')
1316 self.assertEqual(A.reported, 1)
1317 self.assertEqual(self.getJobFromHistory('project-merge').result,
1318 'SUCCESS')
1319 self.assertEqual(self.getJobFromHistory('project-test1').result,
1320 'SUCCESS')
1321 self.assertEqual(self.getJobFromHistory('project-test2').result,
1322 'SUCCESS')
James E. Blaire0487072012-08-29 17:38:31 -07001323
1324 def test_check_queue_failure(self):
1325 "Test failed check queue jobs."
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001326
James E. Blaire0487072012-08-29 17:38:31 -07001327 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001328 self.worker.addFailTest('project-test2', A)
James E. Blaire0487072012-08-29 17:38:31 -07001329 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1330
1331 self.waitUntilSettled()
James E. Blaire0487072012-08-29 17:38:31 -07001332
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001333 self.assertEqual(A.data['status'], 'NEW')
1334 self.assertEqual(A.reported, 1)
1335 self.assertEqual(self.getJobFromHistory('project-merge').result,
James E. Blair78e31b32013-07-09 09:11:34 -07001336 'SUCCESS')
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001337 self.assertEqual(self.getJobFromHistory('project-test1').result,
1338 'SUCCESS')
1339 self.assertEqual(self.getJobFromHistory('project-test2').result,
1340 'FAILURE')
James E. Blair127bc182012-08-28 15:55:15 -07001341
1342 def test_dependent_behind_dequeue(self):
1343 "test that dependent changes behind dequeued changes work"
1344 # This complicated test is a reproduction of a real life bug
1345 self.sched.reconfigure(self.config)
James E. Blair127bc182012-08-28 15:55:15 -07001346
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001347 self.worker.hold_jobs_in_build = True
James E. Blair127bc182012-08-28 15:55:15 -07001348 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
1349 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
1350 C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
1351 D = self.fake_gerrit.addFakeChange('org/project2', 'master', 'D')
1352 E = self.fake_gerrit.addFakeChange('org/project2', 'master', 'E')
1353 F = self.fake_gerrit.addFakeChange('org/project3', 'master', 'F')
1354 D.setDependsOn(C, 1)
1355 E.setDependsOn(D, 1)
1356 A.addApproval('CRVW', 2)
1357 B.addApproval('CRVW', 2)
1358 C.addApproval('CRVW', 2)
1359 D.addApproval('CRVW', 2)
1360 E.addApproval('CRVW', 2)
1361 F.addApproval('CRVW', 2)
1362
1363 A.fail_merge = True
James E. Blair127bc182012-08-28 15:55:15 -07001364
1365 # Change object re-use in the gerrit trigger is hidden if
1366 # changes are added in quick succession; waiting makes it more
1367 # like real life.
1368 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1369 self.waitUntilSettled()
1370 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1371 self.waitUntilSettled()
1372
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001373 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001374 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001375 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001376 self.waitUntilSettled()
1377
1378 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1379 self.waitUntilSettled()
1380 self.fake_gerrit.addEvent(D.addApproval('APRV', 1))
1381 self.waitUntilSettled()
1382 self.fake_gerrit.addEvent(E.addApproval('APRV', 1))
1383 self.waitUntilSettled()
1384 self.fake_gerrit.addEvent(F.addApproval('APRV', 1))
1385 self.waitUntilSettled()
1386
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001387 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001388 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001389 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001390 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001391 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001392 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001393 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001394 self.waitUntilSettled()
1395
1396 # all jobs running
James E. Blaire955e062012-10-08 09:49:03 -07001397
1398 # Grab pointers to the jobs we want to release before
1399 # releasing any, because list indexes may change as
1400 # the jobs complete.
Monty Taylor6bef8ef2013-06-02 08:17:12 -04001401 a, b, c = self.builds[:3]
James E. Blaire955e062012-10-08 09:49:03 -07001402 a.release()
1403 b.release()
1404 c.release()
James E. Blair127bc182012-08-28 15:55:15 -07001405 self.waitUntilSettled()
1406
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001407 self.worker.hold_jobs_in_build = False
1408 self.worker.release()
James E. Blair127bc182012-08-28 15:55:15 -07001409 self.waitUntilSettled()
1410
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001411 self.assertEqual(A.data['status'], 'NEW')
1412 self.assertEqual(B.data['status'], 'MERGED')
1413 self.assertEqual(C.data['status'], 'MERGED')
1414 self.assertEqual(D.data['status'], 'MERGED')
1415 self.assertEqual(E.data['status'], 'MERGED')
1416 self.assertEqual(F.data['status'], 'MERGED')
James E. Blair127bc182012-08-28 15:55:15 -07001417
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001418 self.assertEqual(A.reported, 2)
1419 self.assertEqual(B.reported, 2)
1420 self.assertEqual(C.reported, 2)
1421 self.assertEqual(D.reported, 2)
1422 self.assertEqual(E.reported, 2)
1423 self.assertEqual(F.reported, 2)
James E. Blair127bc182012-08-28 15:55:15 -07001424
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001425 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 15)
1426 self.assertEqual(len(self.history), 44)
James E. Blair05fed602012-09-07 12:45:24 -07001427
1428 def test_merger_repack(self):
1429 "Test that the merger works after a repack"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001430
James E. Blair05fed602012-09-07 12:45:24 -07001431 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1432 A.addApproval('CRVW', 2)
1433 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1434 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001435 self.assertEqual(self.getJobFromHistory('project-merge').result,
1436 'SUCCESS')
1437 self.assertEqual(self.getJobFromHistory('project-test1').result,
1438 'SUCCESS')
1439 self.assertEqual(self.getJobFromHistory('project-test2').result,
1440 'SUCCESS')
1441 self.assertEqual(A.data['status'], 'MERGED')
1442 self.assertEqual(A.reported, 2)
James E. Blair05fed602012-09-07 12:45:24 -07001443 self.assertEmptyQueues()
James E. Blair4ca985f2013-05-30 12:27:43 -07001444 self.worker.build_history = []
James E. Blair05fed602012-09-07 12:45:24 -07001445
Monty Taylorbc758832013-06-17 17:22:42 -04001446 path = os.path.join(self.git_root, "org/project")
1447 print repack_repo(path)
James E. Blair05fed602012-09-07 12:45:24 -07001448
1449 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1450 A.addApproval('CRVW', 2)
1451 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1452 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001453 self.assertEqual(self.getJobFromHistory('project-merge').result,
1454 'SUCCESS')
1455 self.assertEqual(self.getJobFromHistory('project-test1').result,
1456 'SUCCESS')
1457 self.assertEqual(self.getJobFromHistory('project-test2').result,
1458 'SUCCESS')
1459 self.assertEqual(A.data['status'], 'MERGED')
1460 self.assertEqual(A.reported, 2)
James E. Blair7ee88a22012-09-12 18:59:31 +02001461
James E. Blair4886f282012-11-15 09:27:33 -08001462 def test_merger_repack_large_change(self):
1463 "Test that the merger works with large changes after a repack"
1464 # https://bugs.launchpad.net/zuul/+bug/1078946
James E. Blairac2c3242014-01-24 13:38:51 -08001465 # This test assumes the repo is already cloned; make sure it is
1466 url = self.sched.triggers['gerrit'].getGitUrl(
1467 self.sched.layout.projects['org/project1'])
James E. Blair4076e2b2014-01-28 12:42:20 -08001468 self.merge_server.merger.addProject('org/project1', url)
James E. Blair4886f282012-11-15 09:27:33 -08001469 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
1470 A.addPatchset(large=True)
Monty Taylorbc758832013-06-17 17:22:42 -04001471 path = os.path.join(self.upstream_root, "org/project1")
1472 print repack_repo(path)
1473 path = os.path.join(self.git_root, "org/project1")
1474 print repack_repo(path)
James E. Blair4886f282012-11-15 09:27:33 -08001475
1476 A.addApproval('CRVW', 2)
1477 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1478 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001479 self.assertEqual(self.getJobFromHistory('project1-merge').result,
1480 'SUCCESS')
1481 self.assertEqual(self.getJobFromHistory('project1-test1').result,
1482 'SUCCESS')
1483 self.assertEqual(self.getJobFromHistory('project1-test2').result,
1484 'SUCCESS')
1485 self.assertEqual(A.data['status'], 'MERGED')
1486 self.assertEqual(A.reported, 2)
James E. Blair4886f282012-11-15 09:27:33 -08001487
James E. Blair7ee88a22012-09-12 18:59:31 +02001488 def test_nonexistent_job(self):
1489 "Test launching a job that doesn't exist"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001490 # Set to the state immediately after a restart
1491 self.resetGearmanServer()
1492 self.launcher.negative_function_cache_ttl = 0
James E. Blair7ee88a22012-09-12 18:59:31 +02001493
1494 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1495 A.addApproval('CRVW', 2)
1496 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1497 # There may be a thread about to report a lost change
1498 while A.reported < 2:
1499 self.waitUntilSettled()
Monty Taylor6bef8ef2013-06-02 08:17:12 -04001500 job_names = [x.name for x in self.history]
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001501 self.assertFalse(job_names)
1502 self.assertEqual(A.data['status'], 'NEW')
1503 self.assertEqual(A.reported, 2)
James E. Blair7ee88a22012-09-12 18:59:31 +02001504 self.assertEmptyQueues()
1505
1506 # Make sure things still work:
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001507 self.registerJobs()
James E. Blair7ee88a22012-09-12 18:59:31 +02001508 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1509 A.addApproval('CRVW', 2)
1510 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1511 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001512 self.assertEqual(self.getJobFromHistory('project-merge').result,
1513 'SUCCESS')
1514 self.assertEqual(self.getJobFromHistory('project-test1').result,
1515 'SUCCESS')
1516 self.assertEqual(self.getJobFromHistory('project-test2').result,
1517 'SUCCESS')
1518 self.assertEqual(A.data['status'], 'MERGED')
1519 self.assertEqual(A.reported, 2)
James E. Blairf62d4282012-12-31 17:01:50 -08001520
1521 def test_single_nonexistent_post_job(self):
1522 "Test launching a single post job that doesn't exist"
James E. Blairf62d4282012-12-31 17:01:50 -08001523 e = {
1524 "type": "ref-updated",
1525 "submitter": {
1526 "name": "User Name",
1527 },
1528 "refUpdate": {
1529 "oldRev": "90f173846e3af9154517b88543ffbd1691f31366",
1530 "newRev": "d479a0bfcb34da57a31adb2a595c0cf687812543",
1531 "refName": "master",
1532 "project": "org/project",
1533 }
1534 }
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001535 # Set to the state immediately after a restart
1536 self.resetGearmanServer()
1537 self.launcher.negative_function_cache_ttl = 0
1538
James E. Blairf62d4282012-12-31 17:01:50 -08001539 self.fake_gerrit.addEvent(e)
1540 self.waitUntilSettled()
1541
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001542 self.assertEqual(len(self.history), 0)
James E. Blair2fa50962013-01-30 21:50:41 -08001543
1544 def test_new_patchset_dequeues_old(self):
1545 "Test that a new patchset causes the old to be dequeued"
1546 # D -> C (depends on B) -> B (depends on A) -> A -> M
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001547 self.worker.hold_jobs_in_build = True
James E. Blair2fa50962013-01-30 21:50:41 -08001548 M = self.fake_gerrit.addFakeChange('org/project', 'master', 'M')
1549 M.setMerged()
1550
1551 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1552 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1553 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1554 D = self.fake_gerrit.addFakeChange('org/project', 'master', 'D')
1555 A.addApproval('CRVW', 2)
1556 B.addApproval('CRVW', 2)
1557 C.addApproval('CRVW', 2)
1558 D.addApproval('CRVW', 2)
1559
1560 C.setDependsOn(B, 1)
1561 B.setDependsOn(A, 1)
1562 A.setDependsOn(M, 1)
1563
1564 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1565 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1566 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1567 self.fake_gerrit.addEvent(D.addApproval('APRV', 1))
1568 self.waitUntilSettled()
1569
1570 B.addPatchset()
1571 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(2))
1572 self.waitUntilSettled()
1573
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001574 self.worker.hold_jobs_in_build = False
1575 self.worker.release()
James E. Blair2fa50962013-01-30 21:50:41 -08001576 self.waitUntilSettled()
1577
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001578 self.assertEqual(A.data['status'], 'MERGED')
1579 self.assertEqual(A.reported, 2)
1580 self.assertEqual(B.data['status'], 'NEW')
1581 self.assertEqual(B.reported, 2)
1582 self.assertEqual(C.data['status'], 'NEW')
1583 self.assertEqual(C.reported, 2)
1584 self.assertEqual(D.data['status'], 'MERGED')
1585 self.assertEqual(D.reported, 2)
1586 self.assertEqual(len(self.history), 9) # 3 each for A, B, D.
James E. Blair2fa50962013-01-30 21:50:41 -08001587
James E. Blairba437362015-02-07 11:41:52 -08001588 def test_new_patchset_check(self):
1589 "Test a new patchset in check"
Antoine Mussobd86a312014-01-08 14:51:33 +01001590
1591 self.worker.hold_jobs_in_build = True
1592
1593 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
James E. Blairba437362015-02-07 11:41:52 -08001594 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1595 check_pipeline = self.sched.layout.pipelines['check']
1596
1597 # Add two git-dependent changes
1598 B.setDependsOn(A, 1)
1599 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1600 self.waitUntilSettled()
Antoine Mussobd86a312014-01-08 14:51:33 +01001601 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1602 self.waitUntilSettled()
James E. Blairba437362015-02-07 11:41:52 -08001603
1604 # A live item, and a non-live/live pair
1605 items = check_pipeline.getAllItems()
1606 self.assertEqual(len(items), 3)
1607
1608 self.assertEqual(items[0].change.number, '1')
1609 self.assertEqual(items[0].change.patchset, '1')
1610 self.assertFalse(items[0].live)
1611
1612 self.assertEqual(items[1].change.number, '2')
1613 self.assertEqual(items[1].change.patchset, '1')
1614 self.assertTrue(items[1].live)
1615
1616 self.assertEqual(items[2].change.number, '1')
1617 self.assertEqual(items[2].change.patchset, '1')
1618 self.assertTrue(items[2].live)
1619
1620 # Add a new patchset to A
1621 A.addPatchset()
1622 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
1623 self.waitUntilSettled()
1624
1625 # The live copy of A,1 should be gone, but the non-live and B
1626 # should continue, and we should have a new A,2
1627 items = check_pipeline.getAllItems()
1628 self.assertEqual(len(items), 3)
1629
1630 self.assertEqual(items[0].change.number, '1')
1631 self.assertEqual(items[0].change.patchset, '1')
1632 self.assertFalse(items[0].live)
1633
1634 self.assertEqual(items[1].change.number, '2')
1635 self.assertEqual(items[1].change.patchset, '1')
1636 self.assertTrue(items[1].live)
1637
1638 self.assertEqual(items[2].change.number, '1')
1639 self.assertEqual(items[2].change.patchset, '2')
1640 self.assertTrue(items[2].live)
1641
1642 # Add a new patchset to B
1643 B.addPatchset()
1644 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(2))
1645 self.waitUntilSettled()
1646
1647 # The live copy of B,1 should be gone, and it's non-live copy of A,1
1648 # but we should have a new B,2 (still based on A,1)
1649 items = check_pipeline.getAllItems()
1650 self.assertEqual(len(items), 3)
1651
1652 self.assertEqual(items[0].change.number, '1')
1653 self.assertEqual(items[0].change.patchset, '2')
1654 self.assertTrue(items[0].live)
1655
1656 self.assertEqual(items[1].change.number, '1')
1657 self.assertEqual(items[1].change.patchset, '1')
1658 self.assertFalse(items[1].live)
1659
1660 self.assertEqual(items[2].change.number, '2')
1661 self.assertEqual(items[2].change.patchset, '2')
1662 self.assertTrue(items[2].live)
1663
1664 self.builds[0].release()
1665 self.waitUntilSettled()
1666 self.builds[0].release()
1667 self.waitUntilSettled()
1668 self.worker.hold_jobs_in_build = False
1669 self.worker.release()
1670 self.waitUntilSettled()
1671
1672 self.assertEqual(A.reported, 1)
1673 self.assertEqual(B.reported, 1)
1674 self.assertEqual(self.history[0].result, 'ABORTED')
1675 self.assertEqual(self.history[0].changes, '1,1')
1676 self.assertEqual(self.history[1].result, 'ABORTED')
1677 self.assertEqual(self.history[1].changes, '1,1 2,1')
1678 self.assertEqual(self.history[2].result, 'SUCCESS')
1679 self.assertEqual(self.history[2].changes, '1,2')
1680 self.assertEqual(self.history[3].result, 'SUCCESS')
1681 self.assertEqual(self.history[3].changes, '1,1 2,2')
1682
1683 def test_abandoned_gate(self):
1684 "Test that an abandoned change is dequeued from gate"
1685
1686 self.worker.hold_jobs_in_build = True
1687
1688 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1689 A.addApproval('CRVW', 2)
1690 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1691 self.waitUntilSettled()
Antoine Mussobd86a312014-01-08 14:51:33 +01001692 self.assertEqual(len(self.builds), 1, "One job being built (on hold)")
1693 self.assertEqual(self.builds[0].name, 'project-merge')
1694
1695 self.fake_gerrit.addEvent(A.getChangeAbandonedEvent())
1696 self.waitUntilSettled()
1697
Antoine Mussobd86a312014-01-08 14:51:33 +01001698 self.worker.release('.*-merge')
1699 self.waitUntilSettled()
1700
1701 self.assertEqual(len(self.builds), 0, "No job running")
Antoine Mussobd86a312014-01-08 14:51:33 +01001702 self.assertEqual(len(self.history), 1, "Only one build in history")
1703 self.assertEqual(self.history[0].result, 'ABORTED',
James E. Blairba437362015-02-07 11:41:52 -08001704 "Build should have been aborted")
1705 self.assertEqual(A.reported, 1,
1706 "Abandoned gate change should report only start")
1707
1708 def test_abandoned_check(self):
1709 "Test that an abandoned change is dequeued from check"
1710
1711 self.worker.hold_jobs_in_build = True
1712
1713 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1714 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1715 check_pipeline = self.sched.layout.pipelines['check']
1716
1717 # Add two git-dependent changes
1718 B.setDependsOn(A, 1)
1719 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1720 self.waitUntilSettled()
1721 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1722 self.waitUntilSettled()
1723 # A live item, and a non-live/live pair
1724 items = check_pipeline.getAllItems()
1725 self.assertEqual(len(items), 3)
1726
1727 self.assertEqual(items[0].change.number, '1')
1728 self.assertFalse(items[0].live)
1729
1730 self.assertEqual(items[1].change.number, '2')
1731 self.assertTrue(items[1].live)
1732
1733 self.assertEqual(items[2].change.number, '1')
1734 self.assertTrue(items[2].live)
1735
1736 # Abandon A
1737 self.fake_gerrit.addEvent(A.getChangeAbandonedEvent())
1738 self.waitUntilSettled()
1739
1740 # The live copy of A should be gone, but the non-live and B
1741 # should continue
1742 items = check_pipeline.getAllItems()
1743 self.assertEqual(len(items), 2)
1744
1745 self.assertEqual(items[0].change.number, '1')
1746 self.assertFalse(items[0].live)
1747
1748 self.assertEqual(items[1].change.number, '2')
1749 self.assertTrue(items[1].live)
1750
1751 self.worker.hold_jobs_in_build = False
1752 self.worker.release()
1753 self.waitUntilSettled()
1754
1755 self.assertEqual(len(self.history), 4)
1756 self.assertEqual(self.history[0].result, 'ABORTED',
Antoine Mussobd86a312014-01-08 14:51:33 +01001757 'Build should have been aborted')
1758 self.assertEqual(A.reported, 0, "Abandoned change should not report")
James E. Blairba437362015-02-07 11:41:52 -08001759 self.assertEqual(B.reported, 1, "Change should report")
Antoine Mussobd86a312014-01-08 14:51:33 +01001760
Arx Cruzb1b010d2013-10-28 19:49:59 -02001761 def test_zuul_url_return(self):
1762 "Test if ZUUL_URL is returning when zuul_url is set in zuul.conf"
James E. Blair4076e2b2014-01-28 12:42:20 -08001763 self.assertTrue(self.sched.config.has_option('merger', 'zuul_url'))
Arx Cruzb1b010d2013-10-28 19:49:59 -02001764 self.worker.hold_jobs_in_build = True
1765
1766 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1767 A.addApproval('CRVW', 2)
1768 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1769 self.waitUntilSettled()
1770
1771 self.assertEqual(len(self.builds), 1)
1772 for build in self.builds:
1773 self.assertTrue('ZUUL_URL' in build.parameters)
1774
1775 self.worker.hold_jobs_in_build = False
1776 self.worker.release()
1777 self.waitUntilSettled()
1778
James E. Blair2fa50962013-01-30 21:50:41 -08001779 def test_new_patchset_dequeues_old_on_head(self):
1780 "Test that a new patchset causes the old to be dequeued (at head)"
1781 # D -> C (depends on B) -> B (depends on A) -> A -> M
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001782 self.worker.hold_jobs_in_build = True
James E. Blair2fa50962013-01-30 21:50:41 -08001783 M = self.fake_gerrit.addFakeChange('org/project', 'master', 'M')
1784 M.setMerged()
1785 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1786 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1787 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1788 D = self.fake_gerrit.addFakeChange('org/project', 'master', 'D')
1789 A.addApproval('CRVW', 2)
1790 B.addApproval('CRVW', 2)
1791 C.addApproval('CRVW', 2)
1792 D.addApproval('CRVW', 2)
1793
1794 C.setDependsOn(B, 1)
1795 B.setDependsOn(A, 1)
1796 A.setDependsOn(M, 1)
1797
1798 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1799 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1800 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1801 self.fake_gerrit.addEvent(D.addApproval('APRV', 1))
1802 self.waitUntilSettled()
1803
1804 A.addPatchset()
1805 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
1806 self.waitUntilSettled()
1807
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001808 self.worker.hold_jobs_in_build = False
1809 self.worker.release()
James E. Blair2fa50962013-01-30 21:50:41 -08001810 self.waitUntilSettled()
1811
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001812 self.assertEqual(A.data['status'], 'NEW')
1813 self.assertEqual(A.reported, 2)
1814 self.assertEqual(B.data['status'], 'NEW')
1815 self.assertEqual(B.reported, 2)
1816 self.assertEqual(C.data['status'], 'NEW')
1817 self.assertEqual(C.reported, 2)
1818 self.assertEqual(D.data['status'], 'MERGED')
1819 self.assertEqual(D.reported, 2)
1820 self.assertEqual(len(self.history), 7)
James E. Blair2fa50962013-01-30 21:50:41 -08001821
1822 def test_new_patchset_dequeues_old_without_dependents(self):
1823 "Test that a new patchset causes only the old to be dequeued"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001824 self.worker.hold_jobs_in_build = True
James E. Blair2fa50962013-01-30 21:50:41 -08001825 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1826 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1827 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1828 A.addApproval('CRVW', 2)
1829 B.addApproval('CRVW', 2)
1830 C.addApproval('CRVW', 2)
1831
1832 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1833 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1834 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1835 self.waitUntilSettled()
1836
1837 B.addPatchset()
1838 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(2))
1839 self.waitUntilSettled()
1840
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001841 self.worker.hold_jobs_in_build = False
1842 self.worker.release()
James E. Blair2fa50962013-01-30 21:50:41 -08001843 self.waitUntilSettled()
1844
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001845 self.assertEqual(A.data['status'], 'MERGED')
1846 self.assertEqual(A.reported, 2)
1847 self.assertEqual(B.data['status'], 'NEW')
1848 self.assertEqual(B.reported, 2)
1849 self.assertEqual(C.data['status'], 'MERGED')
1850 self.assertEqual(C.reported, 2)
1851 self.assertEqual(len(self.history), 9)
James E. Blair2fa50962013-01-30 21:50:41 -08001852
1853 def test_new_patchset_dequeues_old_independent_queue(self):
1854 "Test that a new patchset causes the old to be dequeued (independent)"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001855 self.worker.hold_jobs_in_build = True
James E. Blair2fa50962013-01-30 21:50:41 -08001856 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1857 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1858 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1859 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1860 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1861 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
1862 self.waitUntilSettled()
1863
1864 B.addPatchset()
1865 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(2))
1866 self.waitUntilSettled()
1867
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001868 self.worker.hold_jobs_in_build = False
1869 self.worker.release()
James E. Blair2fa50962013-01-30 21:50:41 -08001870 self.waitUntilSettled()
1871
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001872 self.assertEqual(A.data['status'], 'NEW')
1873 self.assertEqual(A.reported, 1)
1874 self.assertEqual(B.data['status'], 'NEW')
1875 self.assertEqual(B.reported, 1)
1876 self.assertEqual(C.data['status'], 'NEW')
1877 self.assertEqual(C.reported, 1)
1878 self.assertEqual(len(self.history), 10)
1879 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 1)
James E. Blair7d0dedc2013-02-21 17:26:09 -08001880
James E. Blair18c64442014-03-18 10:14:45 -07001881 def test_noop_job(self):
1882 "Test that the internal noop job works"
1883 A = self.fake_gerrit.addFakeChange('org/noop-project', 'master', 'A')
1884 A.addApproval('CRVW', 2)
1885 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1886 self.waitUntilSettled()
1887
1888 self.assertEqual(len(self.gearman_server.getQueue()), 0)
1889 self.assertTrue(self.sched._areAllBuildsComplete())
1890 self.assertEqual(len(self.history), 0)
1891 self.assertEqual(A.data['status'], 'MERGED')
1892 self.assertEqual(A.reported, 2)
1893
James E. Blair7d0dedc2013-02-21 17:26:09 -08001894 def test_zuul_refs(self):
1895 "Test that zuul refs exist and have the right changes"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001896 self.worker.hold_jobs_in_build = True
James E. Blair7d0dedc2013-02-21 17:26:09 -08001897 M1 = self.fake_gerrit.addFakeChange('org/project1', 'master', 'M1')
1898 M1.setMerged()
1899 M2 = self.fake_gerrit.addFakeChange('org/project2', 'master', 'M2')
1900 M2.setMerged()
1901
1902 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
1903 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
1904 C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
1905 D = self.fake_gerrit.addFakeChange('org/project2', 'master', 'D')
1906 A.addApproval('CRVW', 2)
1907 B.addApproval('CRVW', 2)
1908 C.addApproval('CRVW', 2)
1909 D.addApproval('CRVW', 2)
1910 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1911 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1912 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1913 self.fake_gerrit.addEvent(D.addApproval('APRV', 1))
1914
1915 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001916 self.worker.release('.*-merge')
James E. Blair7d0dedc2013-02-21 17:26:09 -08001917 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001918 self.worker.release('.*-merge')
James E. Blair7d0dedc2013-02-21 17:26:09 -08001919 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001920 self.worker.release('.*-merge')
James E. Blair7d0dedc2013-02-21 17:26:09 -08001921 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001922 self.worker.release('.*-merge')
James E. Blair7d0dedc2013-02-21 17:26:09 -08001923 self.waitUntilSettled()
1924
James E. Blair7d0dedc2013-02-21 17:26:09 -08001925 a_zref = b_zref = c_zref = d_zref = None
Monty Taylor6bef8ef2013-06-02 08:17:12 -04001926 for x in self.builds:
James E. Blair7d0dedc2013-02-21 17:26:09 -08001927 if x.parameters['ZUUL_CHANGE'] == '3':
1928 a_zref = x.parameters['ZUUL_REF']
1929 if x.parameters['ZUUL_CHANGE'] == '4':
1930 b_zref = x.parameters['ZUUL_REF']
1931 if x.parameters['ZUUL_CHANGE'] == '5':
1932 c_zref = x.parameters['ZUUL_REF']
1933 if x.parameters['ZUUL_CHANGE'] == '6':
1934 d_zref = x.parameters['ZUUL_REF']
1935
1936 # There are... four... refs.
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001937 self.assertIsNotNone(a_zref)
1938 self.assertIsNotNone(b_zref)
1939 self.assertIsNotNone(c_zref)
1940 self.assertIsNotNone(d_zref)
James E. Blair7d0dedc2013-02-21 17:26:09 -08001941
1942 # And they should all be different
1943 refs = set([a_zref, b_zref, c_zref, d_zref])
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001944 self.assertEqual(len(refs), 4)
James E. Blair7d0dedc2013-02-21 17:26:09 -08001945
1946 # a ref should have a, not b, and should not be in project2
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001947 self.assertTrue(self.ref_has_change(a_zref, A))
1948 self.assertFalse(self.ref_has_change(a_zref, B))
1949 self.assertFalse(self.ref_has_change(a_zref, M2))
James E. Blair7d0dedc2013-02-21 17:26:09 -08001950
1951 # b ref should have a and b, and should not be in project2
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001952 self.assertTrue(self.ref_has_change(b_zref, A))
1953 self.assertTrue(self.ref_has_change(b_zref, B))
1954 self.assertFalse(self.ref_has_change(b_zref, M2))
James E. Blair7d0dedc2013-02-21 17:26:09 -08001955
1956 # c ref should have a and b in 1, c in 2
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001957 self.assertTrue(self.ref_has_change(c_zref, A))
1958 self.assertTrue(self.ref_has_change(c_zref, B))
1959 self.assertTrue(self.ref_has_change(c_zref, C))
1960 self.assertFalse(self.ref_has_change(c_zref, D))
James E. Blair7d0dedc2013-02-21 17:26:09 -08001961
1962 # d ref should have a and b in 1, c and d in 2
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001963 self.assertTrue(self.ref_has_change(d_zref, A))
1964 self.assertTrue(self.ref_has_change(d_zref, B))
1965 self.assertTrue(self.ref_has_change(d_zref, C))
1966 self.assertTrue(self.ref_has_change(d_zref, D))
James E. Blair7d0dedc2013-02-21 17:26:09 -08001967
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001968 self.worker.hold_jobs_in_build = False
1969 self.worker.release()
James E. Blair7d0dedc2013-02-21 17:26:09 -08001970 self.waitUntilSettled()
1971
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001972 self.assertEqual(A.data['status'], 'MERGED')
1973 self.assertEqual(A.reported, 2)
1974 self.assertEqual(B.data['status'], 'MERGED')
1975 self.assertEqual(B.reported, 2)
1976 self.assertEqual(C.data['status'], 'MERGED')
1977 self.assertEqual(C.reported, 2)
1978 self.assertEqual(D.data['status'], 'MERGED')
1979 self.assertEqual(D.reported, 2)
James E. Blair70c71582013-03-06 08:50:50 -08001980
James E. Blair4a28a882013-08-23 15:17:33 -07001981 def test_rerun_on_error(self):
1982 "Test that if a worker fails to run a job, it is run again"
1983 self.worker.hold_jobs_in_build = True
1984 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1985 A.addApproval('CRVW', 2)
1986 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1987 self.waitUntilSettled()
1988
1989 self.builds[0].run_error = True
1990 self.worker.hold_jobs_in_build = False
1991 self.worker.release()
1992 self.waitUntilSettled()
1993 self.assertEqual(self.countJobResults(self.history, 'RUN_ERROR'), 1)
1994 self.assertEqual(self.countJobResults(self.history, 'SUCCESS'), 3)
1995
James E. Blair412e5582013-04-22 15:50:12 -07001996 def test_statsd(self):
1997 "Test each of the statsd methods used in the scheduler"
1998 import extras
1999 statsd = extras.try_import('statsd.statsd')
2000 statsd.incr('test-incr')
2001 statsd.timing('test-timing', 3)
Alex Gaynor813d39b2014-05-17 16:17:16 -07002002 statsd.gauge('test-gauge', 12)
James E. Blair412e5582013-04-22 15:50:12 -07002003 self.assertReportedStat('test-incr', '1|c')
2004 self.assertReportedStat('test-timing', '3|ms')
Alex Gaynor813d39b2014-05-17 16:17:16 -07002005 self.assertReportedStat('test-gauge', '12|g')
James E. Blair412e5582013-04-22 15:50:12 -07002006
James E. Blairdad52252014-02-07 16:59:17 -08002007 def test_stuck_job_cleanup(self):
2008 "Test that pending jobs are cleaned up if removed from layout"
James E. Blair18c64442014-03-18 10:14:45 -07002009 # This job won't be registered at startup because it is not in
2010 # the standard layout, but we need it to already be registerd
2011 # for when we reconfigure, as that is when Zuul will attempt
2012 # to run the new job.
2013 self.worker.registerFunction('build:gate-noop')
James E. Blairdad52252014-02-07 16:59:17 -08002014 self.gearman_server.hold_jobs_in_queue = True
2015 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2016 A.addApproval('CRVW', 2)
2017 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2018 self.waitUntilSettled()
2019 self.assertEqual(len(self.gearman_server.getQueue()), 1)
2020
2021 self.config.set('zuul', 'layout_config',
2022 'tests/fixtures/layout-no-jobs.yaml')
2023 self.sched.reconfigure(self.config)
2024 self.waitUntilSettled()
2025
James E. Blair18c64442014-03-18 10:14:45 -07002026 self.gearman_server.release('gate-noop')
James E. Blairdad52252014-02-07 16:59:17 -08002027 self.waitUntilSettled()
2028 self.assertEqual(len(self.gearman_server.getQueue()), 0)
2029 self.assertTrue(self.sched._areAllBuildsComplete())
2030
2031 self.assertEqual(len(self.history), 1)
James E. Blair18c64442014-03-18 10:14:45 -07002032 self.assertEqual(self.history[0].name, 'gate-noop')
James E. Blairdad52252014-02-07 16:59:17 -08002033 self.assertEqual(self.history[0].result, 'SUCCESS')
2034
James E. Blair70c71582013-03-06 08:50:50 -08002035 def test_file_jobs(self):
2036 "Test that file jobs run only when appropriate"
2037 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2038 A.addPatchset(['pip-requires'])
2039 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2040 A.addApproval('CRVW', 2)
2041 B.addApproval('CRVW', 2)
2042 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2043 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2044 self.waitUntilSettled()
2045
Monty Taylor6bef8ef2013-06-02 08:17:12 -04002046 testfile_jobs = [x for x in self.history
James E. Blair70c71582013-03-06 08:50:50 -08002047 if x.name == 'project-testfile']
2048
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002049 self.assertEqual(len(testfile_jobs), 1)
2050 self.assertEqual(testfile_jobs[0].changes, '1,2')
2051 self.assertEqual(A.data['status'], 'MERGED')
2052 self.assertEqual(A.reported, 2)
2053 self.assertEqual(B.data['status'], 'MERGED')
2054 self.assertEqual(B.reported, 2)
James E. Blair3c5e5b52013-04-26 11:17:03 -07002055
Maru Newby3fe5f852015-01-13 04:22:14 +00002056 def _test_skip_if_jobs(self, branch, should_skip):
2057 "Test that jobs with a skip-if filter run only when appropriate"
2058 self.config.set('zuul', 'layout_config',
2059 'tests/fixtures/layout-skip-if.yaml')
2060 self.sched.reconfigure(self.config)
2061 self.registerJobs()
2062
2063 change = self.fake_gerrit.addFakeChange('org/project',
2064 branch,
2065 'test skip-if')
2066 self.fake_gerrit.addEvent(change.getPatchsetCreatedEvent(1))
2067 self.waitUntilSettled()
2068
2069 tested_change_ids = [x.changes[0] for x in self.history
2070 if x.name == 'project-test-skip-if']
2071
2072 if should_skip:
2073 self.assertEqual([], tested_change_ids)
2074 else:
2075 self.assertIn(change.data['number'], tested_change_ids)
2076
2077 def test_skip_if_match_skips_job(self):
2078 self._test_skip_if_jobs(branch='master', should_skip=True)
2079
2080 def test_skip_if_no_match_runs_job(self):
2081 self._test_skip_if_jobs(branch='mp', should_skip=False)
2082
James E. Blair3c5e5b52013-04-26 11:17:03 -07002083 def test_test_config(self):
2084 "Test that we can test the config"
2085 sched = zuul.scheduler.Scheduler()
James E. Blair6c358e72013-07-29 17:06:47 -07002086 sched.registerTrigger(None, 'gerrit')
James E. Blair63bb0ef2013-07-29 17:14:51 -07002087 sched.registerTrigger(None, 'timer')
James E. Blairc494d542014-08-06 09:23:52 -07002088 sched.registerTrigger(None, 'zuul')
Clark Boylanb640e052014-04-03 16:41:46 -07002089 sched.testConfig(self.config.get('zuul', 'layout_config'))
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002090
2091 def test_build_description(self):
2092 "Test that build descriptions update"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002093 self.worker.registerFunction('set_description:' +
2094 self.worker.worker_id)
2095
2096 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2097 A.addApproval('CRVW', 2)
2098 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2099 self.waitUntilSettled()
Monty Taylor6bef8ef2013-06-02 08:17:12 -04002100 desc = self.history[0].description
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002101 self.log.debug("Description: %s" % desc)
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002102 self.assertTrue(re.search("Branch.*master", desc))
2103 self.assertTrue(re.search("Pipeline.*gate", desc))
2104 self.assertTrue(re.search("project-merge.*SUCCESS", desc))
2105 self.assertTrue(re.search("project-test1.*SUCCESS", desc))
2106 self.assertTrue(re.search("project-test2.*SUCCESS", desc))
2107 self.assertTrue(re.search("Reported result.*SUCCESS", desc))
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002108
James E. Blairc8a1e052014-02-25 09:29:26 -08002109 def test_queue_names(self):
2110 "Test shared change queue names"
2111 project1 = self.sched.layout.projects['org/project1']
2112 project2 = self.sched.layout.projects['org/project2']
2113 q1 = self.sched.layout.pipelines['gate'].getQueue(project1)
2114 q2 = self.sched.layout.pipelines['gate'].getQueue(project2)
2115 self.assertEqual(q1.name, 'integration')
2116 self.assertEqual(q2.name, 'integration')
2117
2118 self.config.set('zuul', 'layout_config',
2119 'tests/fixtures/layout-bad-queue.yaml')
2120 with testtools.ExpectedException(
2121 Exception, "More than one name assigned to change queue"):
2122 self.sched.reconfigure(self.config)
2123
James E. Blair64ed6f22013-07-10 14:07:23 -07002124 def test_queue_precedence(self):
2125 "Test that queue precedence works"
2126
2127 self.gearman_server.hold_jobs_in_queue = True
James E. Blair8de58bd2013-07-18 16:23:33 -07002128 self.worker.hold_jobs_in_build = True
James E. Blair64ed6f22013-07-10 14:07:23 -07002129 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2130 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2131 A.addApproval('CRVW', 2)
2132 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2133
2134 self.waitUntilSettled()
2135 self.gearman_server.hold_jobs_in_queue = False
2136 self.gearman_server.release()
2137 self.waitUntilSettled()
2138
James E. Blair8de58bd2013-07-18 16:23:33 -07002139 # Run one build at a time to ensure non-race order:
2140 for x in range(6):
2141 self.release(self.builds[0])
2142 self.waitUntilSettled()
2143 self.worker.hold_jobs_in_build = False
2144 self.waitUntilSettled()
2145
James E. Blair64ed6f22013-07-10 14:07:23 -07002146 self.log.debug(self.history)
2147 self.assertEqual(self.history[0].pipeline, 'gate')
2148 self.assertEqual(self.history[1].pipeline, 'check')
2149 self.assertEqual(self.history[2].pipeline, 'gate')
2150 self.assertEqual(self.history[3].pipeline, 'gate')
2151 self.assertEqual(self.history[4].pipeline, 'check')
2152 self.assertEqual(self.history[5].pipeline, 'check')
2153
Clark Boylana5edbe42014-06-03 16:39:10 -07002154 def test_json_status(self):
James E. Blair1843a552013-07-03 14:19:52 -07002155 "Test that we can retrieve JSON status info"
2156 self.worker.hold_jobs_in_build = True
2157 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2158 A.addApproval('CRVW', 2)
2159 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2160 self.waitUntilSettled()
2161
2162 port = self.webapp.server.socket.getsockname()[1]
2163
Yuriy Taradaya6d452f2014-04-16 12:36:20 +04002164 req = urllib2.Request("http://localhost:%s/status.json" % port)
Yuriy Taradaya6d452f2014-04-16 12:36:20 +04002165 f = urllib2.urlopen(req)
Clark Boylanaa4f2e72014-06-03 21:22:40 -07002166 headers = f.info()
2167 self.assertIn('Content-Length', headers)
2168 self.assertIn('Content-Type', headers)
2169 self.assertEqual(headers['Content-Type'],
2170 'application/json; charset=UTF-8')
2171 self.assertIn('Last-Modified', headers)
James E. Blair1843a552013-07-03 14:19:52 -07002172 data = f.read()
2173
2174 self.worker.hold_jobs_in_build = False
2175 self.worker.release()
2176 self.waitUntilSettled()
2177
2178 data = json.loads(data)
2179 status_jobs = set()
2180 for p in data['pipelines']:
2181 for q in p['change_queues']:
James E. Blairbfb8e042014-12-30 17:01:44 -08002182 if p['name'] in ['gate', 'conflict']:
Clark Boylanaf2476f2014-01-23 14:47:36 -08002183 self.assertEqual(q['window'], 20)
2184 else:
2185 self.assertEqual(q['window'], 0)
James E. Blair1843a552013-07-03 14:19:52 -07002186 for head in q['heads']:
2187 for change in head:
Clark Boylanaf2476f2014-01-23 14:47:36 -08002188 self.assertTrue(change['active'])
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002189 self.assertEqual(change['id'], '1,1')
James E. Blair1843a552013-07-03 14:19:52 -07002190 for job in change['jobs']:
2191 status_jobs.add(job['name'])
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002192 self.assertIn('project-merge', status_jobs)
2193 self.assertIn('project-test1', status_jobs)
2194 self.assertIn('project-test2', status_jobs)
James E. Blair1843a552013-07-03 14:19:52 -07002195
James E. Blairc3d428e2013-12-03 15:06:48 -08002196 def test_merging_queues(self):
2197 "Test that transitively-connected change queues are merged"
2198 self.config.set('zuul', 'layout_config',
2199 'tests/fixtures/layout-merge-queues.yaml')
2200 self.sched.reconfigure(self.config)
2201 self.assertEqual(len(self.sched.layout.pipelines['gate'].queues), 1)
2202
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002203 def test_node_label(self):
2204 "Test that a job runs on a specific node label"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002205 self.worker.registerFunction('build:node-project-test1:debian')
2206
2207 A = self.fake_gerrit.addFakeChange('org/node-project', 'master', 'A')
2208 A.addApproval('CRVW', 2)
2209 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2210 self.waitUntilSettled()
James E. Blair4ca985f2013-05-30 12:27:43 -07002211
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002212 self.assertIsNone(self.getJobFromHistory('node-project-merge').node)
2213 self.assertEqual(self.getJobFromHistory('node-project-test1').node,
2214 'debian')
2215 self.assertIsNone(self.getJobFromHistory('node-project-test2').node)
James E. Blaircdccd972013-07-01 12:10:22 -07002216
2217 def test_live_reconfiguration(self):
2218 "Test that live reconfiguration works"
2219 self.worker.hold_jobs_in_build = True
2220 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2221 A.addApproval('CRVW', 2)
2222 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2223 self.waitUntilSettled()
2224
2225 self.sched.reconfigure(self.config)
2226
2227 self.worker.hold_jobs_in_build = False
2228 self.worker.release()
2229 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002230 self.assertEqual(self.getJobFromHistory('project-merge').result,
2231 'SUCCESS')
2232 self.assertEqual(self.getJobFromHistory('project-test1').result,
2233 'SUCCESS')
2234 self.assertEqual(self.getJobFromHistory('project-test2').result,
2235 'SUCCESS')
2236 self.assertEqual(A.data['status'], 'MERGED')
2237 self.assertEqual(A.reported, 2)
James E. Blair287c06d2013-07-24 10:39:30 -07002238
James E. Blaire712d9f2013-07-31 11:40:11 -07002239 def test_live_reconfiguration_functions(self):
2240 "Test live reconfiguration with a custom function"
2241 self.worker.registerFunction('build:node-project-test1:debian')
2242 self.worker.registerFunction('build:node-project-test1:wheezy')
2243 A = self.fake_gerrit.addFakeChange('org/node-project', 'master', 'A')
2244 A.addApproval('CRVW', 2)
2245 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2246 self.waitUntilSettled()
2247
2248 self.assertIsNone(self.getJobFromHistory('node-project-merge').node)
2249 self.assertEqual(self.getJobFromHistory('node-project-test1').node,
2250 'debian')
2251 self.assertIsNone(self.getJobFromHistory('node-project-test2').node)
2252
2253 self.config.set('zuul', 'layout_config',
2254 'tests/fixtures/layout-live-'
2255 'reconfiguration-functions.yaml')
2256 self.sched.reconfigure(self.config)
2257 self.worker.build_history = []
2258
2259 B = self.fake_gerrit.addFakeChange('org/node-project', 'master', 'B')
2260 B.addApproval('CRVW', 2)
2261 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2262 self.waitUntilSettled()
2263
2264 self.assertIsNone(self.getJobFromHistory('node-project-merge').node)
2265 self.assertEqual(self.getJobFromHistory('node-project-test1').node,
2266 'wheezy')
2267 self.assertIsNone(self.getJobFromHistory('node-project-test2').node)
2268
James E. Blair287c06d2013-07-24 10:39:30 -07002269 def test_delayed_repo_init(self):
2270 self.config.set('zuul', 'layout_config',
2271 'tests/fixtures/layout-delayed-repo-init.yaml')
2272 self.sched.reconfigure(self.config)
2273
2274 self.init_repo("org/new-project")
2275 A = self.fake_gerrit.addFakeChange('org/new-project', 'master', 'A')
2276
2277 A.addApproval('CRVW', 2)
2278 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2279 self.waitUntilSettled()
2280 self.assertEqual(self.getJobFromHistory('project-merge').result,
2281 'SUCCESS')
2282 self.assertEqual(self.getJobFromHistory('project-test1').result,
2283 'SUCCESS')
2284 self.assertEqual(self.getJobFromHistory('project-test2').result,
2285 'SUCCESS')
2286 self.assertEqual(A.data['status'], 'MERGED')
2287 self.assertEqual(A.reported, 2)
James E. Blair63bb0ef2013-07-29 17:14:51 -07002288
Clark Boylan6dbbc482013-10-18 10:57:31 -07002289 def test_repo_deleted(self):
2290 self.config.set('zuul', 'layout_config',
2291 'tests/fixtures/layout-repo-deleted.yaml')
2292 self.sched.reconfigure(self.config)
2293
2294 self.init_repo("org/delete-project")
2295 A = self.fake_gerrit.addFakeChange('org/delete-project', 'master', 'A')
2296
2297 A.addApproval('CRVW', 2)
2298 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2299 self.waitUntilSettled()
2300 self.assertEqual(self.getJobFromHistory('project-merge').result,
2301 'SUCCESS')
2302 self.assertEqual(self.getJobFromHistory('project-test1').result,
2303 'SUCCESS')
2304 self.assertEqual(self.getJobFromHistory('project-test2').result,
2305 'SUCCESS')
2306 self.assertEqual(A.data['status'], 'MERGED')
2307 self.assertEqual(A.reported, 2)
2308
2309 # Delete org/new-project zuul repo. Should be recloned.
2310 shutil.rmtree(os.path.join(self.git_root, "org/delete-project"))
2311
2312 B = self.fake_gerrit.addFakeChange('org/delete-project', 'master', 'B')
2313
2314 B.addApproval('CRVW', 2)
2315 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2316 self.waitUntilSettled()
2317 self.assertEqual(self.getJobFromHistory('project-merge').result,
2318 'SUCCESS')
2319 self.assertEqual(self.getJobFromHistory('project-test1').result,
2320 'SUCCESS')
2321 self.assertEqual(self.getJobFromHistory('project-test2').result,
2322 'SUCCESS')
2323 self.assertEqual(B.data['status'], 'MERGED')
2324 self.assertEqual(B.reported, 2)
2325
James E. Blair63bb0ef2013-07-29 17:14:51 -07002326 def test_timer(self):
2327 "Test that a periodic job is triggered"
2328 self.worker.hold_jobs_in_build = True
2329 self.config.set('zuul', 'layout_config',
2330 'tests/fixtures/layout-timer.yaml')
2331 self.sched.reconfigure(self.config)
2332 self.registerJobs()
2333
Clark Boylan3ee090a2014-04-03 20:55:09 -07002334 # The pipeline triggers every second, so we should have seen
2335 # several by now.
2336 time.sleep(5)
James E. Blair63bb0ef2013-07-29 17:14:51 -07002337 self.waitUntilSettled()
Clark Boylan3ee090a2014-04-03 20:55:09 -07002338
2339 self.assertEqual(len(self.builds), 2)
2340
James E. Blair63bb0ef2013-07-29 17:14:51 -07002341 port = self.webapp.server.socket.getsockname()[1]
2342
2343 f = urllib.urlopen("http://localhost:%s/status.json" % port)
2344 data = f.read()
2345
2346 self.worker.hold_jobs_in_build = False
Clark Boylan3ee090a2014-04-03 20:55:09 -07002347 # Stop queuing timer triggered jobs so that the assertions
2348 # below don't race against more jobs being queued.
2349 self.config.set('zuul', 'layout_config',
2350 'tests/fixtures/layout-no-timer.yaml')
2351 self.sched.reconfigure(self.config)
2352 self.registerJobs()
James E. Blair63bb0ef2013-07-29 17:14:51 -07002353 self.worker.release()
2354 self.waitUntilSettled()
2355
2356 self.assertEqual(self.getJobFromHistory(
2357 'project-bitrot-stable-old').result, 'SUCCESS')
2358 self.assertEqual(self.getJobFromHistory(
2359 'project-bitrot-stable-older').result, 'SUCCESS')
2360
2361 data = json.loads(data)
2362 status_jobs = set()
2363 for p in data['pipelines']:
2364 for q in p['change_queues']:
2365 for head in q['heads']:
2366 for change in head:
Alex Gaynorddb9ef32013-09-16 21:04:58 -07002367 self.assertEqual(change['id'], None)
James E. Blair63bb0ef2013-07-29 17:14:51 -07002368 for job in change['jobs']:
2369 status_jobs.add(job['name'])
2370 self.assertIn('project-bitrot-stable-old', status_jobs)
2371 self.assertIn('project-bitrot-stable-older', status_jobs)
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002372
James E. Blair4f6033c2014-03-27 15:49:09 -07002373 def test_idle(self):
2374 "Test that frequent periodic jobs work"
2375 self.worker.hold_jobs_in_build = True
James E. Blair4f6033c2014-03-27 15:49:09 -07002376
Clark Boylan3ee090a2014-04-03 20:55:09 -07002377 for x in range(1, 3):
2378 # Test that timer triggers periodic jobs even across
2379 # layout config reloads.
2380 # Start timer trigger
2381 self.config.set('zuul', 'layout_config',
2382 'tests/fixtures/layout-idle.yaml')
2383 self.sched.reconfigure(self.config)
2384 self.registerJobs()
James E. Blair4f6033c2014-03-27 15:49:09 -07002385
Clark Boylan3ee090a2014-04-03 20:55:09 -07002386 # The pipeline triggers every second, so we should have seen
2387 # several by now.
2388 time.sleep(5)
2389 self.waitUntilSettled()
2390
2391 # Stop queuing timer triggered jobs so that the assertions
2392 # below don't race against more jobs being queued.
2393 self.config.set('zuul', 'layout_config',
2394 'tests/fixtures/layout-no-timer.yaml')
2395 self.sched.reconfigure(self.config)
2396 self.registerJobs()
2397
2398 self.assertEqual(len(self.builds), 2)
2399 self.worker.release('.*')
2400 self.waitUntilSettled()
2401 self.assertEqual(len(self.builds), 0)
2402 self.assertEqual(len(self.history), x * 2)
James E. Blair4f6033c2014-03-27 15:49:09 -07002403
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002404 def test_check_smtp_pool(self):
2405 self.config.set('zuul', 'layout_config',
2406 'tests/fixtures/layout-smtp.yaml')
2407 self.sched.reconfigure(self.config)
2408
2409 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2410 self.waitUntilSettled()
2411
2412 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2413 self.waitUntilSettled()
2414
James E. Blairff80a2f2013-12-27 13:24:06 -08002415 self.assertEqual(len(self.smtp_messages), 2)
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002416
2417 # A.messages only holds what FakeGerrit places in it. Thus we
2418 # work on the knowledge of what the first message should be as
2419 # it is only configured to go to SMTP.
2420
2421 self.assertEqual('zuul@example.com',
James E. Blairff80a2f2013-12-27 13:24:06 -08002422 self.smtp_messages[0]['from_email'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002423 self.assertEqual(['you@example.com'],
James E. Blairff80a2f2013-12-27 13:24:06 -08002424 self.smtp_messages[0]['to_email'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002425 self.assertEqual('Starting check jobs.',
James E. Blairff80a2f2013-12-27 13:24:06 -08002426 self.smtp_messages[0]['body'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002427
2428 self.assertEqual('zuul_from@example.com',
James E. Blairff80a2f2013-12-27 13:24:06 -08002429 self.smtp_messages[1]['from_email'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002430 self.assertEqual(['alternative_me@example.com'],
James E. Blairff80a2f2013-12-27 13:24:06 -08002431 self.smtp_messages[1]['to_email'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002432 self.assertEqual(A.messages[0],
James E. Blairff80a2f2013-12-27 13:24:06 -08002433 self.smtp_messages[1]['body'])
James E. Blairad28e912013-11-27 10:43:22 -08002434
James E. Blaire5910202013-12-27 09:50:31 -08002435 def test_timer_smtp(self):
2436 "Test that a periodic job is triggered"
Clark Boylan3ee090a2014-04-03 20:55:09 -07002437 self.worker.hold_jobs_in_build = True
James E. Blaire5910202013-12-27 09:50:31 -08002438 self.config.set('zuul', 'layout_config',
2439 'tests/fixtures/layout-timer-smtp.yaml')
2440 self.sched.reconfigure(self.config)
2441 self.registerJobs()
2442
Clark Boylan3ee090a2014-04-03 20:55:09 -07002443 # The pipeline triggers every second, so we should have seen
2444 # several by now.
2445 time.sleep(5)
James E. Blaire5910202013-12-27 09:50:31 -08002446 self.waitUntilSettled()
2447
Clark Boylan3ee090a2014-04-03 20:55:09 -07002448 self.assertEqual(len(self.builds), 2)
2449 self.worker.release('.*')
2450 self.waitUntilSettled()
2451 self.assertEqual(len(self.history), 2)
2452
James E. Blaire5910202013-12-27 09:50:31 -08002453 self.assertEqual(self.getJobFromHistory(
2454 'project-bitrot-stable-old').result, 'SUCCESS')
2455 self.assertEqual(self.getJobFromHistory(
2456 'project-bitrot-stable-older').result, 'SUCCESS')
2457
James E. Blairff80a2f2013-12-27 13:24:06 -08002458 self.assertEqual(len(self.smtp_messages), 1)
James E. Blaire5910202013-12-27 09:50:31 -08002459
2460 # A.messages only holds what FakeGerrit places in it. Thus we
2461 # work on the knowledge of what the first message should be as
2462 # it is only configured to go to SMTP.
2463
2464 self.assertEqual('zuul_from@example.com',
James E. Blairff80a2f2013-12-27 13:24:06 -08002465 self.smtp_messages[0]['from_email'])
James E. Blaire5910202013-12-27 09:50:31 -08002466 self.assertEqual(['alternative_me@example.com'],
James E. Blairff80a2f2013-12-27 13:24:06 -08002467 self.smtp_messages[0]['to_email'])
James E. Blaire5910202013-12-27 09:50:31 -08002468 self.assertIn('Subject: Periodic check for org/project succeeded',
James E. Blairff80a2f2013-12-27 13:24:06 -08002469 self.smtp_messages[0]['headers'])
James E. Blaire5910202013-12-27 09:50:31 -08002470
Clark Boylan3ee090a2014-04-03 20:55:09 -07002471 # Stop queuing timer triggered jobs and let any that may have
2472 # queued through so that end of test assertions pass.
2473 self.config.set('zuul', 'layout_config',
2474 'tests/fixtures/layout-no-timer.yaml')
2475 self.sched.reconfigure(self.config)
2476 self.registerJobs()
James E. Blairf8058972014-08-15 16:09:16 -07002477 self.waitUntilSettled()
Clark Boylan3ee090a2014-04-03 20:55:09 -07002478 self.worker.release('.*')
2479 self.waitUntilSettled()
2480
James E. Blairad28e912013-11-27 10:43:22 -08002481 def test_client_enqueue(self):
2482 "Test that the RPC client can enqueue a change"
2483 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2484 A.addApproval('CRVW', 2)
2485 A.addApproval('APRV', 1)
2486
2487 client = zuul.rpcclient.RPCClient('127.0.0.1',
2488 self.gearman_server.port)
2489 r = client.enqueue(pipeline='gate',
2490 project='org/project',
2491 trigger='gerrit',
James E. Blair36658cf2013-12-06 17:53:48 -08002492 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08002493 self.waitUntilSettled()
2494 self.assertEqual(self.getJobFromHistory('project-merge').result,
2495 'SUCCESS')
2496 self.assertEqual(self.getJobFromHistory('project-test1').result,
2497 'SUCCESS')
2498 self.assertEqual(self.getJobFromHistory('project-test2').result,
2499 'SUCCESS')
2500 self.assertEqual(A.data['status'], 'MERGED')
2501 self.assertEqual(A.reported, 2)
2502 self.assertEqual(r, True)
2503
2504 def test_client_enqueue_negative(self):
2505 "Test that the RPC client returns errors"
2506 client = zuul.rpcclient.RPCClient('127.0.0.1',
2507 self.gearman_server.port)
2508 with testtools.ExpectedException(zuul.rpcclient.RPCFailure,
2509 "Invalid project"):
2510 r = client.enqueue(pipeline='gate',
2511 project='project-does-not-exist',
2512 trigger='gerrit',
James E. Blair36658cf2013-12-06 17:53:48 -08002513 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08002514 client.shutdown()
2515 self.assertEqual(r, False)
2516
2517 with testtools.ExpectedException(zuul.rpcclient.RPCFailure,
2518 "Invalid pipeline"):
2519 r = client.enqueue(pipeline='pipeline-does-not-exist',
2520 project='org/project',
2521 trigger='gerrit',
James E. Blair36658cf2013-12-06 17:53:48 -08002522 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08002523 client.shutdown()
2524 self.assertEqual(r, False)
2525
2526 with testtools.ExpectedException(zuul.rpcclient.RPCFailure,
2527 "Invalid trigger"):
2528 r = client.enqueue(pipeline='gate',
2529 project='org/project',
2530 trigger='trigger-does-not-exist',
James E. Blair36658cf2013-12-06 17:53:48 -08002531 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08002532 client.shutdown()
2533 self.assertEqual(r, False)
2534
2535 with testtools.ExpectedException(zuul.rpcclient.RPCFailure,
2536 "Invalid change"):
2537 r = client.enqueue(pipeline='gate',
2538 project='org/project',
2539 trigger='gerrit',
James E. Blair36658cf2013-12-06 17:53:48 -08002540 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08002541 client.shutdown()
2542 self.assertEqual(r, False)
2543
2544 self.waitUntilSettled()
2545 self.assertEqual(len(self.history), 0)
2546 self.assertEqual(len(self.builds), 0)
James E. Blair36658cf2013-12-06 17:53:48 -08002547
2548 def test_client_promote(self):
2549 "Test that the RPC client can promote a change"
2550 self.worker.hold_jobs_in_build = True
2551 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2552 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2553 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
2554 A.addApproval('CRVW', 2)
2555 B.addApproval('CRVW', 2)
2556 C.addApproval('CRVW', 2)
2557
2558 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2559 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2560 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
2561
2562 self.waitUntilSettled()
2563
Sean Daguef39b9ca2014-01-10 21:34:35 -05002564 items = self.sched.layout.pipelines['gate'].getAllItems()
2565 enqueue_times = {}
2566 for item in items:
2567 enqueue_times[str(item.change)] = item.enqueue_time
2568
James E. Blair36658cf2013-12-06 17:53:48 -08002569 client = zuul.rpcclient.RPCClient('127.0.0.1',
2570 self.gearman_server.port)
2571 r = client.promote(pipeline='gate',
2572 change_ids=['2,1', '3,1'])
2573
Sean Daguef39b9ca2014-01-10 21:34:35 -05002574 # ensure that enqueue times are durable
2575 items = self.sched.layout.pipelines['gate'].getAllItems()
2576 for item in items:
2577 self.assertEqual(
2578 enqueue_times[str(item.change)], item.enqueue_time)
2579
James E. Blair78acec92014-02-06 07:11:32 -08002580 self.waitUntilSettled()
James E. Blair36658cf2013-12-06 17:53:48 -08002581 self.worker.release('.*-merge')
2582 self.waitUntilSettled()
2583 self.worker.release('.*-merge')
2584 self.waitUntilSettled()
2585 self.worker.release('.*-merge')
2586 self.waitUntilSettled()
2587
2588 self.assertEqual(len(self.builds), 6)
2589 self.assertEqual(self.builds[0].name, 'project-test1')
2590 self.assertEqual(self.builds[1].name, 'project-test2')
2591 self.assertEqual(self.builds[2].name, 'project-test1')
2592 self.assertEqual(self.builds[3].name, 'project-test2')
2593 self.assertEqual(self.builds[4].name, 'project-test1')
2594 self.assertEqual(self.builds[5].name, 'project-test2')
2595
2596 self.assertTrue(self.job_has_changes(self.builds[0], B))
2597 self.assertFalse(self.job_has_changes(self.builds[0], A))
2598 self.assertFalse(self.job_has_changes(self.builds[0], C))
2599
2600 self.assertTrue(self.job_has_changes(self.builds[2], B))
2601 self.assertTrue(self.job_has_changes(self.builds[2], C))
2602 self.assertFalse(self.job_has_changes(self.builds[2], A))
2603
2604 self.assertTrue(self.job_has_changes(self.builds[4], B))
2605 self.assertTrue(self.job_has_changes(self.builds[4], C))
2606 self.assertTrue(self.job_has_changes(self.builds[4], A))
2607
2608 self.worker.release()
2609 self.waitUntilSettled()
2610
2611 self.assertEqual(A.data['status'], 'MERGED')
2612 self.assertEqual(A.reported, 2)
2613 self.assertEqual(B.data['status'], 'MERGED')
2614 self.assertEqual(B.reported, 2)
2615 self.assertEqual(C.data['status'], 'MERGED')
2616 self.assertEqual(C.reported, 2)
2617
2618 client.shutdown()
2619 self.assertEqual(r, True)
2620
2621 def test_client_promote_dependent(self):
2622 "Test that the RPC client can promote a dependent change"
2623 # C (depends on B) -> B -> A ; then promote C to get:
2624 # A -> C (depends on B) -> B
2625 self.worker.hold_jobs_in_build = True
2626 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2627 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2628 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
2629
2630 C.setDependsOn(B, 1)
2631
2632 A.addApproval('CRVW', 2)
2633 B.addApproval('CRVW', 2)
2634 C.addApproval('CRVW', 2)
2635
2636 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2637 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2638 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
2639
2640 self.waitUntilSettled()
2641
2642 client = zuul.rpcclient.RPCClient('127.0.0.1',
2643 self.gearman_server.port)
2644 r = client.promote(pipeline='gate',
2645 change_ids=['3,1'])
2646
James E. Blair78acec92014-02-06 07:11:32 -08002647 self.waitUntilSettled()
James E. Blair36658cf2013-12-06 17:53:48 -08002648 self.worker.release('.*-merge')
2649 self.waitUntilSettled()
2650 self.worker.release('.*-merge')
2651 self.waitUntilSettled()
2652 self.worker.release('.*-merge')
2653 self.waitUntilSettled()
2654
2655 self.assertEqual(len(self.builds), 6)
2656 self.assertEqual(self.builds[0].name, 'project-test1')
2657 self.assertEqual(self.builds[1].name, 'project-test2')
2658 self.assertEqual(self.builds[2].name, 'project-test1')
2659 self.assertEqual(self.builds[3].name, 'project-test2')
2660 self.assertEqual(self.builds[4].name, 'project-test1')
2661 self.assertEqual(self.builds[5].name, 'project-test2')
2662
2663 self.assertTrue(self.job_has_changes(self.builds[0], B))
2664 self.assertFalse(self.job_has_changes(self.builds[0], A))
2665 self.assertFalse(self.job_has_changes(self.builds[0], C))
2666
2667 self.assertTrue(self.job_has_changes(self.builds[2], B))
2668 self.assertTrue(self.job_has_changes(self.builds[2], C))
2669 self.assertFalse(self.job_has_changes(self.builds[2], A))
2670
2671 self.assertTrue(self.job_has_changes(self.builds[4], B))
2672 self.assertTrue(self.job_has_changes(self.builds[4], C))
2673 self.assertTrue(self.job_has_changes(self.builds[4], A))
2674
2675 self.worker.release()
2676 self.waitUntilSettled()
2677
2678 self.assertEqual(A.data['status'], 'MERGED')
2679 self.assertEqual(A.reported, 2)
2680 self.assertEqual(B.data['status'], 'MERGED')
2681 self.assertEqual(B.reported, 2)
2682 self.assertEqual(C.data['status'], 'MERGED')
2683 self.assertEqual(C.reported, 2)
2684
2685 client.shutdown()
2686 self.assertEqual(r, True)
2687
2688 def test_client_promote_negative(self):
2689 "Test that the RPC client returns errors for promotion"
2690 self.worker.hold_jobs_in_build = True
2691 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2692 A.addApproval('CRVW', 2)
2693 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2694 self.waitUntilSettled()
2695
2696 client = zuul.rpcclient.RPCClient('127.0.0.1',
2697 self.gearman_server.port)
2698
2699 with testtools.ExpectedException(zuul.rpcclient.RPCFailure):
2700 r = client.promote(pipeline='nonexistent',
2701 change_ids=['2,1', '3,1'])
2702 client.shutdown()
2703 self.assertEqual(r, False)
2704
2705 with testtools.ExpectedException(zuul.rpcclient.RPCFailure):
2706 r = client.promote(pipeline='gate',
2707 change_ids=['4,1'])
2708 client.shutdown()
2709 self.assertEqual(r, False)
2710
2711 self.worker.hold_jobs_in_build = False
2712 self.worker.release()
2713 self.waitUntilSettled()
Clark Boylan7603a372014-01-21 11:43:20 -08002714
2715 def test_queue_rate_limiting(self):
2716 "Test that DependentPipelines are rate limited with dep across window"
2717 self.config.set('zuul', 'layout_config',
2718 'tests/fixtures/layout-rate-limit.yaml')
2719 self.sched.reconfigure(self.config)
2720 self.worker.hold_jobs_in_build = True
2721 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2722 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2723 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
2724
2725 C.setDependsOn(B, 1)
2726 self.worker.addFailTest('project-test1', A)
2727
2728 A.addApproval('CRVW', 2)
2729 B.addApproval('CRVW', 2)
2730 C.addApproval('CRVW', 2)
2731
2732 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2733 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2734 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
2735 self.waitUntilSettled()
2736
2737 # Only A and B will have their merge jobs queued because
2738 # window is 2.
2739 self.assertEqual(len(self.builds), 2)
2740 self.assertEqual(self.builds[0].name, 'project-merge')
2741 self.assertEqual(self.builds[1].name, 'project-merge')
2742
2743 self.worker.release('.*-merge')
2744 self.waitUntilSettled()
2745 self.worker.release('.*-merge')
2746 self.waitUntilSettled()
2747
2748 # Only A and B will have their test jobs queued because
2749 # window is 2.
2750 self.assertEqual(len(self.builds), 4)
2751 self.assertEqual(self.builds[0].name, 'project-test1')
2752 self.assertEqual(self.builds[1].name, 'project-test2')
2753 self.assertEqual(self.builds[2].name, 'project-test1')
2754 self.assertEqual(self.builds[3].name, 'project-test2')
2755
2756 self.worker.release('project-.*')
2757 self.waitUntilSettled()
2758
2759 queue = self.sched.layout.pipelines['gate'].queues[0]
2760 # A failed so window is reduced by 1 to 1.
2761 self.assertEqual(queue.window, 1)
2762 self.assertEqual(queue.window_floor, 1)
2763 self.assertEqual(A.data['status'], 'NEW')
2764
2765 # Gate is reset and only B's merge job is queued because
2766 # window shrunk to 1.
2767 self.assertEqual(len(self.builds), 1)
2768 self.assertEqual(self.builds[0].name, 'project-merge')
2769
2770 self.worker.release('.*-merge')
2771 self.waitUntilSettled()
2772
2773 # Only B's test jobs are queued because window is still 1.
2774 self.assertEqual(len(self.builds), 2)
2775 self.assertEqual(self.builds[0].name, 'project-test1')
2776 self.assertEqual(self.builds[1].name, 'project-test2')
2777
2778 self.worker.release('project-.*')
2779 self.waitUntilSettled()
2780
2781 # B was successfully merged so window is increased to 2.
2782 self.assertEqual(queue.window, 2)
2783 self.assertEqual(queue.window_floor, 1)
2784 self.assertEqual(B.data['status'], 'MERGED')
2785
2786 # Only C is left and its merge job is queued.
2787 self.assertEqual(len(self.builds), 1)
2788 self.assertEqual(self.builds[0].name, 'project-merge')
2789
2790 self.worker.release('.*-merge')
2791 self.waitUntilSettled()
2792
2793 # After successful merge job the test jobs for C are queued.
2794 self.assertEqual(len(self.builds), 2)
2795 self.assertEqual(self.builds[0].name, 'project-test1')
2796 self.assertEqual(self.builds[1].name, 'project-test2')
2797
2798 self.worker.release('project-.*')
2799 self.waitUntilSettled()
2800
2801 # C successfully merged so window is bumped to 3.
2802 self.assertEqual(queue.window, 3)
2803 self.assertEqual(queue.window_floor, 1)
2804 self.assertEqual(C.data['status'], 'MERGED')
2805
2806 def test_queue_rate_limiting_dependent(self):
2807 "Test that DependentPipelines are rate limited with dep in window"
2808 self.config.set('zuul', 'layout_config',
2809 'tests/fixtures/layout-rate-limit.yaml')
2810 self.sched.reconfigure(self.config)
2811 self.worker.hold_jobs_in_build = True
2812 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2813 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2814 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
2815
2816 B.setDependsOn(A, 1)
2817
2818 self.worker.addFailTest('project-test1', A)
2819
2820 A.addApproval('CRVW', 2)
2821 B.addApproval('CRVW', 2)
2822 C.addApproval('CRVW', 2)
2823
2824 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2825 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2826 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
2827 self.waitUntilSettled()
2828
2829 # Only A and B will have their merge jobs queued because
2830 # window is 2.
2831 self.assertEqual(len(self.builds), 2)
2832 self.assertEqual(self.builds[0].name, 'project-merge')
2833 self.assertEqual(self.builds[1].name, 'project-merge')
2834
2835 self.worker.release('.*-merge')
2836 self.waitUntilSettled()
2837 self.worker.release('.*-merge')
2838 self.waitUntilSettled()
2839
2840 # Only A and B will have their test jobs queued because
2841 # window is 2.
2842 self.assertEqual(len(self.builds), 4)
2843 self.assertEqual(self.builds[0].name, 'project-test1')
2844 self.assertEqual(self.builds[1].name, 'project-test2')
2845 self.assertEqual(self.builds[2].name, 'project-test1')
2846 self.assertEqual(self.builds[3].name, 'project-test2')
2847
2848 self.worker.release('project-.*')
2849 self.waitUntilSettled()
2850
2851 queue = self.sched.layout.pipelines['gate'].queues[0]
2852 # A failed so window is reduced by 1 to 1.
2853 self.assertEqual(queue.window, 1)
2854 self.assertEqual(queue.window_floor, 1)
2855 self.assertEqual(A.data['status'], 'NEW')
2856 self.assertEqual(B.data['status'], 'NEW')
2857
2858 # Gate is reset and only C's merge job is queued because
2859 # window shrunk to 1 and A and B were dequeued.
2860 self.assertEqual(len(self.builds), 1)
2861 self.assertEqual(self.builds[0].name, 'project-merge')
2862
2863 self.worker.release('.*-merge')
2864 self.waitUntilSettled()
2865
2866 # Only C's test jobs are queued because window is still 1.
2867 self.assertEqual(len(self.builds), 2)
2868 self.assertEqual(self.builds[0].name, 'project-test1')
2869 self.assertEqual(self.builds[1].name, 'project-test2')
2870
2871 self.worker.release('project-.*')
2872 self.waitUntilSettled()
2873
2874 # C was successfully merged so window is increased to 2.
2875 self.assertEqual(queue.window, 2)
2876 self.assertEqual(queue.window_floor, 1)
2877 self.assertEqual(C.data['status'], 'MERGED')
Joshua Heskethba8776a2014-01-12 14:35:40 +08002878
2879 def test_worker_update_metadata(self):
2880 "Test if a worker can send back metadata about itself"
2881 self.worker.hold_jobs_in_build = True
2882
2883 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2884 A.addApproval('CRVW', 2)
2885 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2886 self.waitUntilSettled()
2887
2888 self.assertEqual(len(self.launcher.builds), 1)
2889
2890 self.log.debug('Current builds:')
2891 self.log.debug(self.launcher.builds)
2892
2893 start = time.time()
2894 while True:
2895 if time.time() - start > 10:
2896 raise Exception("Timeout waiting for gearman server to report "
2897 + "back to the client")
2898 build = self.launcher.builds.values()[0]
2899 if build.worker.name == "My Worker":
2900 break
2901 else:
2902 time.sleep(0)
2903
2904 self.log.debug(build)
2905 self.assertEqual("My Worker", build.worker.name)
2906 self.assertEqual("localhost", build.worker.hostname)
2907 self.assertEqual(['127.0.0.1', '192.168.1.1'], build.worker.ips)
2908 self.assertEqual("zuul.example.org", build.worker.fqdn)
2909 self.assertEqual("FakeBuilder", build.worker.program)
2910 self.assertEqual("v1.1", build.worker.version)
2911 self.assertEqual({'something': 'else'}, build.worker.extra)
2912
2913 self.worker.hold_jobs_in_build = False
2914 self.worker.release()
2915 self.waitUntilSettled()
Joshua Hesketh3979e3e2014-03-04 11:21:10 +11002916
2917 def test_footer_message(self):
2918 "Test a pipeline's footer message is correctly added to the report."
2919 self.config.set('zuul', 'layout_config',
2920 'tests/fixtures/layout-footer-message.yaml')
2921 self.sched.reconfigure(self.config)
2922 self.registerJobs()
2923
2924 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2925 A.addApproval('CRVW', 2)
2926 self.worker.addFailTest('test1', A)
2927 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2928 self.waitUntilSettled()
2929
2930 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2931 B.addApproval('CRVW', 2)
2932 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2933 self.waitUntilSettled()
2934
2935 self.assertEqual(2, len(self.smtp_messages))
2936
2937 failure_body = """\
2938Build failed. For information on how to proceed, see \
2939http://wiki.example.org/Test_Failures
2940
2941- test1 http://logs.example.com/1/1/gate/test1/0 : FAILURE in 0s
2942- test2 http://logs.example.com/1/1/gate/test2/1 : SUCCESS in 0s
2943
2944For CI problems and help debugging, contact ci@example.org"""
2945
2946 success_body = """\
2947Build succeeded.
2948
2949- test1 http://logs.example.com/2/1/gate/test1/2 : SUCCESS in 0s
2950- test2 http://logs.example.com/2/1/gate/test2/3 : SUCCESS in 0s
2951
2952For CI problems and help debugging, contact ci@example.org"""
2953
2954 self.assertEqual(failure_body, self.smtp_messages[0]['body'])
2955 self.assertEqual(success_body, self.smtp_messages[1]['body'])
Joshua Heskethb7179772014-01-30 23:30:46 +11002956
2957 def test_merge_failure_reporters(self):
2958 """Check that the config is set up correctly"""
2959
2960 self.config.set('zuul', 'layout_config',
2961 'tests/fixtures/layout-merge-failure.yaml')
2962 self.sched.reconfigure(self.config)
2963 self.registerJobs()
2964
2965 self.assertEqual(
2966 "Merge Failed.\n\nThis change was unable to be automatically "
2967 "merged with the current state of the repository. Please rebase "
2968 "your change and upload a new patchset.",
2969 self.sched.layout.pipelines['check'].merge_failure_message)
2970 self.assertEqual(
2971 "The merge failed! For more information...",
2972 self.sched.layout.pipelines['gate'].merge_failure_message)
2973
2974 self.assertEqual(
2975 len(self.sched.layout.pipelines['check'].merge_failure_actions), 1)
2976 self.assertEqual(
2977 len(self.sched.layout.pipelines['gate'].merge_failure_actions), 2)
2978
2979 self.assertTrue(isinstance(
2980 self.sched.layout.pipelines['check'].merge_failure_actions[0].
2981 reporter, zuul.reporter.gerrit.Reporter))
2982
2983 self.assertTrue(
2984 (
2985 isinstance(self.sched.layout.pipelines['gate'].
2986 merge_failure_actions[0].reporter,
2987 zuul.reporter.smtp.Reporter) and
2988 isinstance(self.sched.layout.pipelines['gate'].
2989 merge_failure_actions[1].reporter,
2990 zuul.reporter.gerrit.Reporter)
2991 ) or (
2992 isinstance(self.sched.layout.pipelines['gate'].
2993 merge_failure_actions[0].reporter,
2994 zuul.reporter.gerrit.Reporter) and
2995 isinstance(self.sched.layout.pipelines['gate'].
2996 merge_failure_actions[1].reporter,
2997 zuul.reporter.smtp.Reporter)
2998 )
2999 )
3000
3001 def test_merge_failure_reports(self):
3002 """Check that when a change fails to merge the correct message is sent
3003 to the correct reporter"""
3004 self.config.set('zuul', 'layout_config',
3005 'tests/fixtures/layout-merge-failure.yaml')
3006 self.sched.reconfigure(self.config)
3007 self.registerJobs()
3008
3009 # Check a test failure isn't reported to SMTP
3010 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3011 A.addApproval('CRVW', 2)
3012 self.worker.addFailTest('project-test1', A)
3013 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3014 self.waitUntilSettled()
3015
3016 self.assertEqual(3, len(self.history)) # 3 jobs
3017 self.assertEqual(0, len(self.smtp_messages))
3018
3019 # Check a merge failure is reported to SMTP
3020 # B should be merged, but C will conflict with B
3021 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
3022 B.addPatchset(['conflict'])
3023 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
3024 C.addPatchset(['conflict'])
3025 B.addApproval('CRVW', 2)
3026 C.addApproval('CRVW', 2)
3027 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3028 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
3029 self.waitUntilSettled()
3030
3031 self.assertEqual(6, len(self.history)) # A and B jobs
3032 self.assertEqual(1, len(self.smtp_messages))
3033 self.assertEqual('The merge failed! For more information...',
3034 self.smtp_messages[0]['body'])
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11003035
3036 def test_swift_instructions(self):
3037 "Test that the correct swift instructions are sent to the workers"
3038 self.config.set('zuul', 'layout_config',
3039 'tests/fixtures/layout-swift.yaml')
3040 self.sched.reconfigure(self.config)
3041 self.registerJobs()
3042
3043 self.worker.hold_jobs_in_build = True
3044 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3045
3046 A.addApproval('CRVW', 2)
3047 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3048 self.waitUntilSettled()
3049
3050 self.assertEqual(
3051 "https://storage.example.org/V1/AUTH_account/merge_logs/1/1/1/"
3052 "gate/test-merge/",
Joshua Hesketh76dee532014-07-03 15:39:13 +10003053 self.builds[0].parameters['SWIFT_logs_URL'][:-7])
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11003054 self.assertEqual(5,
3055 len(self.builds[0].parameters['SWIFT_logs_HMAC_BODY'].
3056 split('\n')))
3057 self.assertIn('SWIFT_logs_SIGNATURE', self.builds[0].parameters)
3058
3059 self.assertEqual(
3060 "https://storage.example.org/V1/AUTH_account/logs/1/1/1/"
3061 "gate/test-test/",
Joshua Hesketh76dee532014-07-03 15:39:13 +10003062 self.builds[1].parameters['SWIFT_logs_URL'][:-7])
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11003063 self.assertEqual(5,
3064 len(self.builds[1].parameters['SWIFT_logs_HMAC_BODY'].
3065 split('\n')))
3066 self.assertIn('SWIFT_logs_SIGNATURE', self.builds[1].parameters)
3067
3068 self.assertEqual(
3069 "https://storage.example.org/V1/AUTH_account/stash/1/1/1/"
3070 "gate/test-test/",
Joshua Hesketh76dee532014-07-03 15:39:13 +10003071 self.builds[1].parameters['SWIFT_MOSTLY_URL'][:-7])
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11003072 self.assertEqual(5,
3073 len(self.builds[1].
3074 parameters['SWIFT_MOSTLY_HMAC_BODY'].split('\n')))
3075 self.assertIn('SWIFT_MOSTLY_SIGNATURE', self.builds[1].parameters)
3076
3077 self.worker.hold_jobs_in_build = False
3078 self.worker.release()
3079 self.waitUntilSettled()
Joshua Hesketh85af4e92014-02-21 08:28:58 -08003080
3081 def test_client_get_running_jobs(self):
3082 "Test that the RPC client can get a list of running jobs"
3083 self.worker.hold_jobs_in_build = True
3084 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3085 A.addApproval('CRVW', 2)
3086 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3087 self.waitUntilSettled()
3088
3089 client = zuul.rpcclient.RPCClient('127.0.0.1',
3090 self.gearman_server.port)
3091
3092 # Wait for gearman server to send the initial workData back to zuul
3093 start = time.time()
3094 while True:
3095 if time.time() - start > 10:
3096 raise Exception("Timeout waiting for gearman server to report "
3097 + "back to the client")
3098 build = self.launcher.builds.values()[0]
3099 if build.worker.name == "My Worker":
3100 break
3101 else:
3102 time.sleep(0)
3103
3104 running_items = client.get_running_jobs()
3105
3106 self.assertEqual(1, len(running_items))
3107 running_item = running_items[0]
3108 self.assertEqual([], running_item['failing_reasons'])
3109 self.assertEqual([], running_item['items_behind'])
3110 self.assertEqual('https://hostname/1', running_item['url'])
3111 self.assertEqual(None, running_item['item_ahead'])
3112 self.assertEqual('org/project', running_item['project'])
3113 self.assertEqual(None, running_item['remaining_time'])
3114 self.assertEqual(True, running_item['active'])
3115 self.assertEqual('1,1', running_item['id'])
3116
3117 self.assertEqual(3, len(running_item['jobs']))
3118 for job in running_item['jobs']:
3119 if job['name'] == 'project-merge':
3120 self.assertEqual('project-merge', job['name'])
3121 self.assertEqual('gate', job['pipeline'])
3122 self.assertEqual(False, job['retry'])
Joshua Hesketh85af4e92014-02-21 08:28:58 -08003123 self.assertEqual('https://server/job/project-merge/0/',
3124 job['url'])
3125 self.assertEqual(7, len(job['worker']))
3126 self.assertEqual(False, job['canceled'])
3127 self.assertEqual(True, job['voting'])
3128 self.assertEqual(None, job['result'])
3129 self.assertEqual('gate', job['pipeline'])
3130 break
3131
3132 self.worker.hold_jobs_in_build = False
3133 self.worker.release()
3134 self.waitUntilSettled()
3135
3136 running_items = client.get_running_jobs()
3137 self.assertEqual(0, len(running_items))
James E. Blairbadc1ad2014-04-28 13:55:14 -07003138
3139 def test_nonvoting_pipeline(self):
3140 "Test that a nonvoting pipeline (experimental) can still report"
3141
Joshua Heskethcc017ea2014-04-30 19:55:25 +10003142 A = self.fake_gerrit.addFakeChange('org/experimental-project',
3143 'master', 'A')
James E. Blairbadc1ad2014-04-28 13:55:14 -07003144 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3145 self.waitUntilSettled()
Joshua Heskethcc017ea2014-04-30 19:55:25 +10003146 self.assertEqual(
3147 self.getJobFromHistory('experimental-project-test').result,
3148 'SUCCESS')
James E. Blairbadc1ad2014-04-28 13:55:14 -07003149 self.assertEqual(A.reported, 1)
James E. Blair5ee24252014-12-30 10:12:29 -08003150
3151 def test_crd_gate(self):
3152 "Test cross-repo dependencies"
3153 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3154 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3155 A.addApproval('CRVW', 2)
3156 B.addApproval('CRVW', 2)
3157
3158 AM2 = self.fake_gerrit.addFakeChange('org/project1', 'master', 'AM2')
3159 AM1 = self.fake_gerrit.addFakeChange('org/project1', 'master', 'AM1')
3160 AM2.setMerged()
3161 AM1.setMerged()
3162
3163 BM2 = self.fake_gerrit.addFakeChange('org/project2', 'master', 'BM2')
3164 BM1 = self.fake_gerrit.addFakeChange('org/project2', 'master', 'BM1')
3165 BM2.setMerged()
3166 BM1.setMerged()
3167
3168 # A -> AM1 -> AM2
3169 # B -> BM1 -> BM2
3170 # A Depends-On: B
3171 # M2 is here to make sure it is never queried. If it is, it
3172 # means zuul is walking down the entire history of merged
3173 # changes.
3174
3175 B.setDependsOn(BM1, 1)
3176 BM1.setDependsOn(BM2, 1)
3177
3178 A.setDependsOn(AM1, 1)
3179 AM1.setDependsOn(AM2, 1)
3180
3181 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3182 A.subject, B.data['id'])
3183
3184 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3185 self.waitUntilSettled()
3186
3187 self.assertEqual(A.data['status'], 'NEW')
3188 self.assertEqual(B.data['status'], 'NEW')
3189
3190 source = self.sched.layout.pipelines['gate'].source
3191 source.maintainCache([])
3192
3193 self.worker.hold_jobs_in_build = True
3194 B.addApproval('APRV', 1)
3195 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3196 self.waitUntilSettled()
3197
3198 self.worker.release('.*-merge')
3199 self.waitUntilSettled()
3200 self.worker.release('.*-merge')
3201 self.waitUntilSettled()
3202 self.worker.hold_jobs_in_build = False
3203 self.worker.release()
3204 self.waitUntilSettled()
3205
3206 self.assertEqual(AM2.queried, 0)
3207 self.assertEqual(BM2.queried, 0)
3208 self.assertEqual(A.data['status'], 'MERGED')
3209 self.assertEqual(B.data['status'], 'MERGED')
3210 self.assertEqual(A.reported, 2)
3211 self.assertEqual(B.reported, 2)
3212
James E. Blair8f78d882015-02-05 08:51:37 -08003213 self.assertEqual(self.getJobFromHistory('project1-merge').changes,
3214 '2,1 1,1')
3215
3216 def test_crd_branch(self):
3217 "Test cross-repo dependencies in multiple branches"
3218 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3219 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3220 C = self.fake_gerrit.addFakeChange('org/project2', 'mp', 'C')
3221 C.data['id'] = B.data['id']
3222 A.addApproval('CRVW', 2)
3223 B.addApproval('CRVW', 2)
3224 C.addApproval('CRVW', 2)
3225
3226 # A Depends-On: B+C
3227 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3228 A.subject, B.data['id'])
3229
3230 self.worker.hold_jobs_in_build = True
3231 B.addApproval('APRV', 1)
3232 C.addApproval('APRV', 1)
3233 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3234 self.waitUntilSettled()
3235
3236 self.worker.release('.*-merge')
3237 self.waitUntilSettled()
3238 self.worker.release('.*-merge')
3239 self.waitUntilSettled()
3240 self.worker.release('.*-merge')
3241 self.waitUntilSettled()
3242 self.worker.hold_jobs_in_build = False
3243 self.worker.release()
3244 self.waitUntilSettled()
3245
3246 self.assertEqual(A.data['status'], 'MERGED')
3247 self.assertEqual(B.data['status'], 'MERGED')
3248 self.assertEqual(C.data['status'], 'MERGED')
3249 self.assertEqual(A.reported, 2)
3250 self.assertEqual(B.reported, 2)
3251 self.assertEqual(C.reported, 2)
3252
3253 self.assertEqual(self.getJobFromHistory('project1-merge').changes,
3254 '2,1 3,1 1,1')
3255
3256 def test_crd_multiline(self):
3257 "Test multiple depends-on lines in commit"
3258 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3259 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3260 C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
3261 A.addApproval('CRVW', 2)
3262 B.addApproval('CRVW', 2)
3263 C.addApproval('CRVW', 2)
3264
3265 # A Depends-On: B+C
3266 A.data['commitMessage'] = '%s\n\nDepends-On: %s\nDepends-On: %s\n' % (
3267 A.subject, B.data['id'], C.data['id'])
3268
3269 self.worker.hold_jobs_in_build = True
3270 B.addApproval('APRV', 1)
3271 C.addApproval('APRV', 1)
3272 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3273 self.waitUntilSettled()
3274
3275 self.worker.release('.*-merge')
3276 self.waitUntilSettled()
3277 self.worker.release('.*-merge')
3278 self.waitUntilSettled()
3279 self.worker.release('.*-merge')
3280 self.waitUntilSettled()
3281 self.worker.hold_jobs_in_build = False
3282 self.worker.release()
3283 self.waitUntilSettled()
3284
3285 self.assertEqual(A.data['status'], 'MERGED')
3286 self.assertEqual(B.data['status'], 'MERGED')
3287 self.assertEqual(C.data['status'], 'MERGED')
3288 self.assertEqual(A.reported, 2)
3289 self.assertEqual(B.reported, 2)
3290 self.assertEqual(C.reported, 2)
3291
3292 self.assertEqual(self.getJobFromHistory('project1-merge').changes,
3293 '2,1 3,1 1,1')
James E. Blair5ee24252014-12-30 10:12:29 -08003294
3295 def test_crd_unshared_gate(self):
3296 "Test cross-repo dependencies in unshared gate queues"
3297 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3298 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
3299 A.addApproval('CRVW', 2)
3300 B.addApproval('CRVW', 2)
3301
3302 # A Depends-On: B
3303 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3304 A.subject, B.data['id'])
3305
3306 # A and B do not share a queue, make sure that A is unable to
3307 # enqueue B (and therefore, A is unable to be enqueued).
3308 B.addApproval('APRV', 1)
3309 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3310 self.waitUntilSettled()
3311
3312 self.assertEqual(A.data['status'], 'NEW')
3313 self.assertEqual(B.data['status'], 'NEW')
3314 self.assertEqual(A.reported, 0)
3315 self.assertEqual(B.reported, 0)
3316 self.assertEqual(len(self.history), 0)
3317
3318 # Enqueue and merge B alone.
3319 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3320 self.waitUntilSettled()
3321
3322 self.assertEqual(B.data['status'], 'MERGED')
3323 self.assertEqual(B.reported, 2)
3324
3325 # Now that B is merged, A should be able to be enqueued and
3326 # merged.
3327 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3328 self.waitUntilSettled()
3329
3330 self.assertEqual(A.data['status'], 'MERGED')
3331 self.assertEqual(A.reported, 2)
3332
James E. Blair96698e22015-04-02 07:48:21 -07003333 def test_crd_gate_reverse(self):
3334 "Test reverse cross-repo dependencies"
3335 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3336 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3337 A.addApproval('CRVW', 2)
3338 B.addApproval('CRVW', 2)
3339
3340 # A Depends-On: B
3341
3342 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3343 A.subject, B.data['id'])
3344
3345 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3346 self.waitUntilSettled()
3347
3348 self.assertEqual(A.data['status'], 'NEW')
3349 self.assertEqual(B.data['status'], 'NEW')
3350
3351 self.worker.hold_jobs_in_build = True
3352 A.addApproval('APRV', 1)
3353 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3354 self.waitUntilSettled()
3355
3356 self.worker.release('.*-merge')
3357 self.waitUntilSettled()
3358 self.worker.release('.*-merge')
3359 self.waitUntilSettled()
3360 self.worker.hold_jobs_in_build = False
3361 self.worker.release()
3362 self.waitUntilSettled()
3363
3364 self.assertEqual(A.data['status'], 'MERGED')
3365 self.assertEqual(B.data['status'], 'MERGED')
3366 self.assertEqual(A.reported, 2)
3367 self.assertEqual(B.reported, 2)
3368
3369 self.assertEqual(self.getJobFromHistory('project1-merge').changes,
3370 '2,1 1,1')
3371
James E. Blair5ee24252014-12-30 10:12:29 -08003372 def test_crd_cycle(self):
3373 "Test cross-repo dependency cycles"
3374 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3375 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3376 A.addApproval('CRVW', 2)
3377 B.addApproval('CRVW', 2)
3378
3379 # A -> B -> A (via commit-depends)
3380
3381 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3382 A.subject, B.data['id'])
3383 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3384 B.subject, A.data['id'])
3385
3386 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3387 self.waitUntilSettled()
3388
3389 self.assertEqual(A.reported, 0)
3390 self.assertEqual(B.reported, 0)
3391 self.assertEqual(A.data['status'], 'NEW')
3392 self.assertEqual(B.data['status'], 'NEW')
James E. Blairbfb8e042014-12-30 17:01:44 -08003393
3394 def test_crd_check(self):
3395 "Test cross-repo dependencies in independent pipelines"
3396
3397 self.gearman_server.hold_jobs_in_queue = True
3398 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3399 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3400
3401 # A Depends-On: B
3402 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3403 A.subject, B.data['id'])
3404
3405 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3406 self.waitUntilSettled()
3407
3408 queue = self.gearman_server.getQueue()
3409 ref = self.getParameter(queue[-1], 'ZUUL_REF')
3410 self.gearman_server.hold_jobs_in_queue = False
3411 self.gearman_server.release()
3412 self.waitUntilSettled()
3413
3414 path = os.path.join(self.git_root, "org/project1")
3415 repo = git.Repo(path)
3416 repo_messages = [c.message.strip() for c in repo.iter_commits(ref)]
3417 repo_messages.reverse()
3418 correct_messages = ['initial commit', 'A-1']
3419 self.assertEqual(repo_messages, correct_messages)
3420
3421 path = os.path.join(self.git_root, "org/project2")
3422 repo = git.Repo(path)
3423 repo_messages = [c.message.strip() for c in repo.iter_commits(ref)]
3424 repo_messages.reverse()
3425 correct_messages = ['initial commit', 'B-1']
3426 self.assertEqual(repo_messages, correct_messages)
3427
3428 self.assertEqual(A.data['status'], 'NEW')
3429 self.assertEqual(B.data['status'], 'NEW')
3430 self.assertEqual(A.reported, 1)
3431 self.assertEqual(B.reported, 0)
3432
3433 self.assertEqual(self.history[0].changes, '2,1 1,1')
3434 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 0)
James E. Blair8f78d882015-02-05 08:51:37 -08003435
James E. Blairdbfe1cd2015-02-07 11:41:19 -08003436 def test_crd_check_git_depends(self):
3437 "Test single-repo dependencies in independent pipelines"
3438 self.gearman_server.hold_jobs_in_queue = True
3439 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3440 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
3441
3442 # Add two git-dependent changes and make sure they both report
3443 # success.
3444 B.setDependsOn(A, 1)
3445 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3446 self.waitUntilSettled()
3447 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
3448 self.waitUntilSettled()
3449
3450 self.gearman_server.hold_jobs_in_queue = False
3451 self.gearman_server.release()
3452 self.waitUntilSettled()
3453
3454 self.assertEqual(A.data['status'], 'NEW')
3455 self.assertEqual(B.data['status'], 'NEW')
3456 self.assertEqual(A.reported, 1)
3457 self.assertEqual(B.reported, 1)
3458
3459 self.assertEqual(self.history[0].changes, '1,1')
3460 self.assertEqual(self.history[-1].changes, '1,1 2,1')
3461 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 0)
3462
3463 self.assertIn('Build succeeded', A.messages[0])
3464 self.assertIn('Build succeeded', B.messages[0])
3465
3466 def test_crd_check_duplicate(self):
3467 "Test duplicate check in independent pipelines"
3468 self.gearman_server.hold_jobs_in_queue = True
3469 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3470 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
3471 check_pipeline = self.sched.layout.pipelines['check']
3472
3473 # Add two git-dependent changes...
3474 B.setDependsOn(A, 1)
3475 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
3476 self.waitUntilSettled()
3477 self.assertEqual(len(check_pipeline.getAllItems()), 2)
3478
3479 # ...make sure the live one is not duplicated...
3480 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
3481 self.waitUntilSettled()
3482 self.assertEqual(len(check_pipeline.getAllItems()), 2)
3483
3484 # ...but the non-live one is able to be.
3485 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3486 self.waitUntilSettled()
3487 self.assertEqual(len(check_pipeline.getAllItems()), 3)
3488
Clark Boylandd849822015-03-02 12:38:14 -08003489 # Release jobs in order to avoid races with change A jobs
3490 # finishing before change B jobs.
James E. Blairdbfe1cd2015-02-07 11:41:19 -08003491 self.gearman_server.release('.*-merge')
Clark Boylandd849822015-03-02 12:38:14 -08003492 self.gearman_server.release('project1-.*')
James E. Blairdbfe1cd2015-02-07 11:41:19 -08003493 self.waitUntilSettled()
3494 self.gearman_server.release('.*-merge')
Clark Boylandd849822015-03-02 12:38:14 -08003495 self.gearman_server.release('project1-.*')
James E. Blairdbfe1cd2015-02-07 11:41:19 -08003496 self.waitUntilSettled()
3497 self.gearman_server.release()
3498 self.waitUntilSettled()
3499
3500 self.assertEqual(A.data['status'], 'NEW')
3501 self.assertEqual(B.data['status'], 'NEW')
3502 self.assertEqual(A.reported, 1)
3503 self.assertEqual(B.reported, 1)
3504
3505 self.assertEqual(self.history[0].changes, '1,1 2,1')
3506 self.assertEqual(self.history[1].changes, '1,1')
3507 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 0)
3508
3509 self.assertIn('Build succeeded', A.messages[0])
3510 self.assertIn('Build succeeded', B.messages[0])
3511
James E. Blair8f78d882015-02-05 08:51:37 -08003512 def test_crd_check_reconfiguration(self):
3513 "Test cross-repo dependencies re-enqueued in independent pipelines"
3514
3515 self.gearman_server.hold_jobs_in_queue = True
3516 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3517 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3518
3519 # A Depends-On: B
3520 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3521 A.subject, B.data['id'])
3522
3523 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3524 self.waitUntilSettled()
3525
3526 self.sched.reconfigure(self.config)
3527
3528 # Make sure the items still share a change queue, and the
3529 # first one is not live.
3530 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 1)
3531 queue = self.sched.layout.pipelines['check'].queues[0]
3532 first_item = queue.queue[0]
3533 for item in queue.queue:
3534 self.assertEqual(item.queue, first_item.queue)
3535 self.assertFalse(first_item.live)
3536 self.assertTrue(queue.queue[1].live)
3537
3538 self.gearman_server.hold_jobs_in_queue = False
3539 self.gearman_server.release()
3540 self.waitUntilSettled()
3541
3542 self.assertEqual(A.data['status'], 'NEW')
3543 self.assertEqual(B.data['status'], 'NEW')
3544 self.assertEqual(A.reported, 1)
3545 self.assertEqual(B.reported, 0)
3546
3547 self.assertEqual(self.history[0].changes, '2,1 1,1')
3548 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 0)
James E. Blair17dd6772015-02-09 14:45:18 -08003549
3550 def test_crd_check_ignore_dependencies(self):
3551 "Test cross-repo dependencies can be ignored"
3552 self.config.set('zuul', 'layout_config',
3553 'tests/fixtures/layout-ignore-dependencies.yaml')
3554 self.sched.reconfigure(self.config)
3555 self.registerJobs()
3556
3557 self.gearman_server.hold_jobs_in_queue = True
3558 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3559 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3560 C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
3561
3562 # A Depends-On: B
3563 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3564 A.subject, B.data['id'])
3565 # C git-depends on B
3566 C.setDependsOn(B, 1)
3567 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3568 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
3569 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
3570 self.waitUntilSettled()
3571
3572 # Make sure none of the items share a change queue, and all
3573 # are live.
3574 check_pipeline = self.sched.layout.pipelines['check']
3575 self.assertEqual(len(check_pipeline.queues), 3)
3576 self.assertEqual(len(check_pipeline.getAllItems()), 3)
3577 for item in check_pipeline.getAllItems():
3578 self.assertTrue(item.live)
3579
3580 self.gearman_server.hold_jobs_in_queue = False
3581 self.gearman_server.release()
3582 self.waitUntilSettled()
3583
3584 self.assertEqual(A.data['status'], 'NEW')
3585 self.assertEqual(B.data['status'], 'NEW')
3586 self.assertEqual(C.data['status'], 'NEW')
3587 self.assertEqual(A.reported, 1)
3588 self.assertEqual(B.reported, 1)
3589 self.assertEqual(C.reported, 1)
3590
3591 # Each job should have tested exactly one change
3592 for job in self.history:
3593 self.assertEqual(len(job.changes.split()), 1)
James E. Blair96698e22015-04-02 07:48:21 -07003594
3595 def test_crd_check_transitive(self):
3596 "Test transitive cross-repo dependencies"
3597 # Specifically, if A -> B -> C, and C gets a new patchset and
3598 # A gets a new patchset, ensure the test of A,2 includes B,1
3599 # and C,2 (not C,1 which would indicate stale data in the
3600 # cache for B).
3601 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3602 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3603 C = self.fake_gerrit.addFakeChange('org/project3', 'master', 'C')
3604
3605 # A Depends-On: B
3606 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3607 A.subject, B.data['id'])
3608
3609 # B Depends-On: C
3610 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3611 B.subject, C.data['id'])
3612
3613 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3614 self.waitUntilSettled()
3615 self.assertEqual(self.history[-1].changes, '3,1 2,1 1,1')
3616
3617 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
3618 self.waitUntilSettled()
3619 self.assertEqual(self.history[-1].changes, '3,1 2,1')
3620
3621 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
3622 self.waitUntilSettled()
3623 self.assertEqual(self.history[-1].changes, '3,1')
3624
3625 C.addPatchset()
3626 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(2))
3627 self.waitUntilSettled()
3628 self.assertEqual(self.history[-1].changes, '3,2')
3629
3630 A.addPatchset()
3631 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
3632 self.waitUntilSettled()
3633 self.assertEqual(self.history[-1].changes, '3,2 2,1 1,2')