blob: 7ef166c4206ef48002431ac619c6d0707a338a40 [file] [log] [blame]
James E. Blairb0fcae42012-07-17 11:12:10 -07001#!/usr/bin/env python
2
3# Copyright 2012 Hewlett-Packard Development Company, L.P.
4#
5# Licensed under the Apache License, Version 2.0 (the "License"); you may
6# not use this file except in compliance with the License. You may obtain
7# a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations
15# under the License.
16
James E. Blairb0fcae42012-07-17 11:12:10 -070017import json
Monty Taylorbc758832013-06-17 17:22:42 -040018import logging
19import os
James E. Blairb0fcae42012-07-17 11:12:10 -070020import re
James E. Blair4886cc12012-07-18 15:39:41 -070021import shutil
Monty Taylorbc758832013-06-17 17:22:42 -040022import time
James E. Blair1843a552013-07-03 14:19:52 -070023import urllib
Monty Taylorbc758832013-06-17 17:22:42 -040024import urllib2
Maru Newby3fe5f852015-01-13 04:22:14 +000025import yaml
Monty Taylorbc758832013-06-17 17:22:42 -040026
James E. Blair4886cc12012-07-18 15:39:41 -070027import git
Monty Taylorbc758832013-06-17 17:22:42 -040028import testtools
James E. Blairb0fcae42012-07-17 11:12:10 -070029
Maru Newby3fe5f852015-01-13 04:22:14 +000030import zuul.change_matcher
James E. Blairb0fcae42012-07-17 11:12:10 -070031import zuul.scheduler
James E. Blairad28e912013-11-27 10:43:22 -080032import zuul.rpcclient
Joshua Hesketh1879cf72013-08-19 14:13:15 +100033import zuul.reporter.gerrit
Joshua Hesketh5fea8672013-08-19 17:32:01 +100034import zuul.reporter.smtp
James E. Blairb0fcae42012-07-17 11:12:10 -070035
Maru Newby3fe5f852015-01-13 04:22:14 +000036from tests.base import (
37 BaseTestCase,
38 ZuulTestCase,
39 repack_repo,
40)
James E. Blairb0fcae42012-07-17 11:12:10 -070041
James E. Blair1f4c2bb2013-04-26 08:40:46 -070042logging.basicConfig(level=logging.DEBUG,
43 format='%(asctime)s %(name)-32s '
44 '%(levelname)-8s %(message)s')
James E. Blairb0fcae42012-07-17 11:12:10 -070045
46
Maru Newby3fe5f852015-01-13 04:22:14 +000047class TestSchedulerConfigParsing(BaseTestCase):
48
49 def test_parse_skip_if(self):
50 job_yaml = """
51jobs:
52 - name: job_name
53 skip-if:
54 - project: ^project_name$
55 branch: ^stable/icehouse$
56 all-files-match-any:
57 - ^filename$
58 - project: ^project2_name$
59 all-files-match-any:
60 - ^filename2$
61 """.strip()
62 data = yaml.load(job_yaml)
63 config_job = data.get('jobs')[0]
Joshua Hesketh352264b2015-08-11 23:42:08 +100064 sched = zuul.scheduler.Scheduler({})
Maru Newby3fe5f852015-01-13 04:22:14 +000065 cm = zuul.change_matcher
66 expected = cm.MatchAny([
67 cm.MatchAll([
68 cm.ProjectMatcher('^project_name$'),
69 cm.BranchMatcher('^stable/icehouse$'),
70 cm.MatchAllFiles([cm.FileMatcher('^filename$')]),
71 ]),
72 cm.MatchAll([
73 cm.ProjectMatcher('^project2_name$'),
74 cm.MatchAllFiles([cm.FileMatcher('^filename2$')]),
75 ]),
76 ])
77 matcher = sched._parseSkipIf(config_job)
78 self.assertEqual(expected, matcher)
79
80
Clark Boylanb640e052014-04-03 16:41:46 -070081class TestScheduler(ZuulTestCase):
Antoine Mussobd86a312014-01-08 14:51:33 +010082
James E. Blair509cada2015-12-08 16:31:16 -080083 def setUp(self):
84 self.skip("Disabled for early v3 development")
85
James E. Blairb0fcae42012-07-17 11:12:10 -070086 def test_jobs_launched(self):
87 "Test that jobs are launched and a change is merged"
James E. Blair1f4c2bb2013-04-26 08:40:46 -070088
James E. Blairb0fcae42012-07-17 11:12:10 -070089 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
James E. Blair8c803f82012-07-31 16:25:42 -070090 A.addApproval('CRVW', 2)
James E. Blairb0fcae42012-07-17 11:12:10 -070091 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
92 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -040093 self.assertEqual(self.getJobFromHistory('project-merge').result,
94 'SUCCESS')
95 self.assertEqual(self.getJobFromHistory('project-test1').result,
96 'SUCCESS')
97 self.assertEqual(self.getJobFromHistory('project-test2').result,
98 'SUCCESS')
99 self.assertEqual(A.data['status'], 'MERGED')
100 self.assertEqual(A.reported, 2)
James E. Blairb0fcae42012-07-17 11:12:10 -0700101
James E. Blair66eeebf2013-07-27 17:44:32 -0700102 self.assertReportedStat('gerrit.event.comment-added', value='1|c')
103 self.assertReportedStat('zuul.pipeline.gate.current_changes',
104 value='1|g')
105 self.assertReportedStat('zuul.pipeline.gate.job.project-merge.SUCCESS',
106 kind='ms')
107 self.assertReportedStat('zuul.pipeline.gate.job.project-merge.SUCCESS',
108 value='1|c')
109 self.assertReportedStat('zuul.pipeline.gate.resident_time', kind='ms')
110 self.assertReportedStat('zuul.pipeline.gate.total_changes',
111 value='1|c')
James E. Blair412e5582013-04-22 15:50:12 -0700112 self.assertReportedStat(
James E. Blair66eeebf2013-07-27 17:44:32 -0700113 'zuul.pipeline.gate.org.project.resident_time', kind='ms')
James E. Blair412e5582013-04-22 15:50:12 -0700114 self.assertReportedStat(
James E. Blair66eeebf2013-07-27 17:44:32 -0700115 'zuul.pipeline.gate.org.project.total_changes', value='1|c')
James E. Blair412e5582013-04-22 15:50:12 -0700116
James E. Blair5821bd92015-09-16 08:48:15 -0700117 for build in self.builds:
118 self.assertEqual(build.parameters['ZUUL_VOTING'], '1')
119
James E. Blair3cb10702013-08-24 08:56:03 -0700120 def test_initial_pipeline_gauges(self):
121 "Test that each pipeline reported its length on start"
122 pipeline_names = self.sched.layout.pipelines.keys()
123 self.assertNotEqual(len(pipeline_names), 0)
124 for name in pipeline_names:
125 self.assertReportedStat('zuul.pipeline.%s.current_changes' % name,
126 value='0|g')
127
James E. Blair42f74822013-05-14 15:18:03 -0700128 def test_duplicate_pipelines(self):
129 "Test that a change matching multiple pipelines works"
James E. Blair1b4d9722013-05-21 10:32:04 -0700130
James E. Blair42f74822013-05-14 15:18:03 -0700131 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
132 self.fake_gerrit.addEvent(A.getChangeRestoredEvent())
133 self.waitUntilSettled()
James E. Blair42f74822013-05-14 15:18:03 -0700134
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400135 self.assertEqual(len(self.history), 2)
Monty Taylor6bef8ef2013-06-02 08:17:12 -0400136 self.history[0].name == 'project-test1'
137 self.history[1].name == 'project-test1'
James E. Blair42f74822013-05-14 15:18:03 -0700138
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400139 self.assertEqual(len(A.messages), 2)
James E. Blair42f74822013-05-14 15:18:03 -0700140 if 'dup1/project-test1' in A.messages[0]:
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400141 self.assertIn('dup1/project-test1', A.messages[0])
142 self.assertNotIn('dup2/project-test1', A.messages[0])
143 self.assertNotIn('dup1/project-test1', A.messages[1])
144 self.assertIn('dup2/project-test1', A.messages[1])
James E. Blair42f74822013-05-14 15:18:03 -0700145 else:
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400146 self.assertIn('dup1/project-test1', A.messages[1])
147 self.assertNotIn('dup2/project-test1', A.messages[1])
148 self.assertNotIn('dup1/project-test1', A.messages[0])
149 self.assertIn('dup2/project-test1', A.messages[0])
James E. Blair42f74822013-05-14 15:18:03 -0700150
James E. Blairb0fcae42012-07-17 11:12:10 -0700151 def test_parallel_changes(self):
152 "Test that changes are tested in parallel and merged in series"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700153
154 self.worker.hold_jobs_in_build = True
James E. Blairb0fcae42012-07-17 11:12:10 -0700155 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
156 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
157 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
James E. Blair8c803f82012-07-31 16:25:42 -0700158 A.addApproval('CRVW', 2)
159 B.addApproval('CRVW', 2)
160 C.addApproval('CRVW', 2)
James E. Blairb0fcae42012-07-17 11:12:10 -0700161
162 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
163 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
164 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
165
166 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400167 self.assertEqual(len(self.builds), 1)
168 self.assertEqual(self.builds[0].name, 'project-merge')
169 self.assertTrue(self.job_has_changes(self.builds[0], A))
James E. Blairb0fcae42012-07-17 11:12:10 -0700170
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700171 self.worker.release('.*-merge')
James E. Blairb0fcae42012-07-17 11:12:10 -0700172 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400173 self.assertEqual(len(self.builds), 3)
174 self.assertEqual(self.builds[0].name, 'project-test1')
175 self.assertTrue(self.job_has_changes(self.builds[0], A))
176 self.assertEqual(self.builds[1].name, 'project-test2')
177 self.assertTrue(self.job_has_changes(self.builds[1], A))
178 self.assertEqual(self.builds[2].name, 'project-merge')
179 self.assertTrue(self.job_has_changes(self.builds[2], A, B))
James E. Blairb0fcae42012-07-17 11:12:10 -0700180
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700181 self.worker.release('.*-merge')
James E. Blairb0fcae42012-07-17 11:12:10 -0700182 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400183 self.assertEqual(len(self.builds), 5)
184 self.assertEqual(self.builds[0].name, 'project-test1')
185 self.assertTrue(self.job_has_changes(self.builds[0], A))
186 self.assertEqual(self.builds[1].name, 'project-test2')
187 self.assertTrue(self.job_has_changes(self.builds[1], A))
James E. Blairb0fcae42012-07-17 11:12:10 -0700188
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400189 self.assertEqual(self.builds[2].name, 'project-test1')
190 self.assertTrue(self.job_has_changes(self.builds[2], A, B))
191 self.assertEqual(self.builds[3].name, 'project-test2')
192 self.assertTrue(self.job_has_changes(self.builds[3], A, B))
James E. Blairb0fcae42012-07-17 11:12:10 -0700193
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400194 self.assertEqual(self.builds[4].name, 'project-merge')
195 self.assertTrue(self.job_has_changes(self.builds[4], A, B, C))
James E. Blairb0fcae42012-07-17 11:12:10 -0700196
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700197 self.worker.release('.*-merge')
James E. Blairb0fcae42012-07-17 11:12:10 -0700198 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400199 self.assertEqual(len(self.builds), 6)
200 self.assertEqual(self.builds[0].name, 'project-test1')
201 self.assertTrue(self.job_has_changes(self.builds[0], A))
202 self.assertEqual(self.builds[1].name, 'project-test2')
203 self.assertTrue(self.job_has_changes(self.builds[1], A))
James E. Blairb0fcae42012-07-17 11:12:10 -0700204
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400205 self.assertEqual(self.builds[2].name, 'project-test1')
206 self.assertTrue(self.job_has_changes(self.builds[2], A, B))
207 self.assertEqual(self.builds[3].name, 'project-test2')
208 self.assertTrue(self.job_has_changes(self.builds[3], A, B))
James E. Blairb0fcae42012-07-17 11:12:10 -0700209
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400210 self.assertEqual(self.builds[4].name, 'project-test1')
211 self.assertTrue(self.job_has_changes(self.builds[4], A, B, C))
212 self.assertEqual(self.builds[5].name, 'project-test2')
213 self.assertTrue(self.job_has_changes(self.builds[5], A, B, C))
James E. Blairb0fcae42012-07-17 11:12:10 -0700214
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700215 self.worker.hold_jobs_in_build = False
216 self.worker.release()
James E. Blairb0fcae42012-07-17 11:12:10 -0700217 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400218 self.assertEqual(len(self.builds), 0)
James E. Blairb0fcae42012-07-17 11:12:10 -0700219
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400220 self.assertEqual(len(self.history), 9)
221 self.assertEqual(A.data['status'], 'MERGED')
222 self.assertEqual(B.data['status'], 'MERGED')
223 self.assertEqual(C.data['status'], 'MERGED')
224 self.assertEqual(A.reported, 2)
225 self.assertEqual(B.reported, 2)
226 self.assertEqual(C.reported, 2)
James E. Blairb02a3bb2012-07-30 17:49:55 -0700227
228 def test_failed_changes(self):
229 "Test that a change behind a failed change is retested"
James E. Blaire2819012013-06-28 17:17:26 -0400230 self.worker.hold_jobs_in_build = True
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700231
James E. Blairb02a3bb2012-07-30 17:49:55 -0700232 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
233 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
James E. Blair8c803f82012-07-31 16:25:42 -0700234 A.addApproval('CRVW', 2)
235 B.addApproval('CRVW', 2)
James E. Blairb02a3bb2012-07-30 17:49:55 -0700236
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700237 self.worker.addFailTest('project-test1', A)
James E. Blairb02a3bb2012-07-30 17:49:55 -0700238
James E. Blaire2819012013-06-28 17:17:26 -0400239 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
240 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
James E. Blairb02a3bb2012-07-30 17:49:55 -0700241 self.waitUntilSettled()
James E. Blaire2819012013-06-28 17:17:26 -0400242
243 self.worker.release('.*-merge')
244 self.waitUntilSettled()
245
246 self.worker.hold_jobs_in_build = False
247 self.worker.release()
248
249 self.waitUntilSettled()
250 # It's certain that the merge job for change 2 will run, but
251 # the test1 and test2 jobs may or may not run.
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400252 self.assertTrue(len(self.history) > 6)
253 self.assertEqual(A.data['status'], 'NEW')
254 self.assertEqual(B.data['status'], 'MERGED')
255 self.assertEqual(A.reported, 2)
256 self.assertEqual(B.reported, 2)
James E. Blairb02a3bb2012-07-30 17:49:55 -0700257
258 def test_independent_queues(self):
259 "Test that changes end up in the right queues"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700260
261 self.worker.hold_jobs_in_build = True
Zhongyue Luo5d556072012-09-21 02:00:47 +0900262 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
James E. Blairb02a3bb2012-07-30 17:49:55 -0700263 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
264 C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
James E. Blair8c803f82012-07-31 16:25:42 -0700265 A.addApproval('CRVW', 2)
266 B.addApproval('CRVW', 2)
267 C.addApproval('CRVW', 2)
James E. Blairb02a3bb2012-07-30 17:49:55 -0700268
269 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
270 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
271 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
272
James E. Blairb02a3bb2012-07-30 17:49:55 -0700273 self.waitUntilSettled()
274
275 # There should be one merge job at the head of each queue running
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400276 self.assertEqual(len(self.builds), 2)
277 self.assertEqual(self.builds[0].name, 'project-merge')
278 self.assertTrue(self.job_has_changes(self.builds[0], A))
279 self.assertEqual(self.builds[1].name, 'project1-merge')
280 self.assertTrue(self.job_has_changes(self.builds[1], B))
James E. Blairb02a3bb2012-07-30 17:49:55 -0700281
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700282 # Release the current merge builds
283 self.worker.release('.*-merge')
James E. Blairb02a3bb2012-07-30 17:49:55 -0700284 self.waitUntilSettled()
285 # Release the merge job for project2 which is behind project1
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700286 self.worker.release('.*-merge')
James E. Blairb02a3bb2012-07-30 17:49:55 -0700287 self.waitUntilSettled()
288
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700289 # All the test builds should be running:
James E. Blairb02a3bb2012-07-30 17:49:55 -0700290 # project1 (3) + project2 (3) + project (2) = 8
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400291 self.assertEqual(len(self.builds), 8)
James E. Blairb02a3bb2012-07-30 17:49:55 -0700292
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700293 self.worker.release()
James E. Blairb02a3bb2012-07-30 17:49:55 -0700294 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400295 self.assertEqual(len(self.builds), 0)
James E. Blairb02a3bb2012-07-30 17:49:55 -0700296
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400297 self.assertEqual(len(self.history), 11)
298 self.assertEqual(A.data['status'], 'MERGED')
299 self.assertEqual(B.data['status'], 'MERGED')
300 self.assertEqual(C.data['status'], 'MERGED')
301 self.assertEqual(A.reported, 2)
302 self.assertEqual(B.reported, 2)
303 self.assertEqual(C.reported, 2)
James E. Blaird466dc42012-07-31 10:42:56 -0700304
305 def test_failed_change_at_head(self):
306 "Test that if a change at the head fails, jobs behind it are canceled"
James E. Blaird466dc42012-07-31 10:42:56 -0700307
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700308 self.worker.hold_jobs_in_build = True
James E. Blaird466dc42012-07-31 10:42:56 -0700309 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
310 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
311 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
James E. Blair8c803f82012-07-31 16:25:42 -0700312 A.addApproval('CRVW', 2)
313 B.addApproval('CRVW', 2)
314 C.addApproval('CRVW', 2)
James E. Blaird466dc42012-07-31 10:42:56 -0700315
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700316 self.worker.addFailTest('project-test1', A)
James E. Blaird466dc42012-07-31 10:42:56 -0700317
318 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
319 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
320 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
321
322 self.waitUntilSettled()
James E. Blaird466dc42012-07-31 10:42:56 -0700323
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400324 self.assertEqual(len(self.builds), 1)
325 self.assertEqual(self.builds[0].name, 'project-merge')
326 self.assertTrue(self.job_has_changes(self.builds[0], A))
James E. Blaird466dc42012-07-31 10:42:56 -0700327
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700328 self.worker.release('.*-merge')
James E. Blaird466dc42012-07-31 10:42:56 -0700329 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700330 self.worker.release('.*-merge')
James E. Blaird466dc42012-07-31 10:42:56 -0700331 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700332 self.worker.release('.*-merge')
James E. Blaird466dc42012-07-31 10:42:56 -0700333 self.waitUntilSettled()
334
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400335 self.assertEqual(len(self.builds), 6)
336 self.assertEqual(self.builds[0].name, 'project-test1')
337 self.assertEqual(self.builds[1].name, 'project-test2')
338 self.assertEqual(self.builds[2].name, 'project-test1')
339 self.assertEqual(self.builds[3].name, 'project-test2')
340 self.assertEqual(self.builds[4].name, 'project-test1')
341 self.assertEqual(self.builds[5].name, 'project-test2')
James E. Blaird466dc42012-07-31 10:42:56 -0700342
Monty Taylor6bef8ef2013-06-02 08:17:12 -0400343 self.release(self.builds[0])
James E. Blaird466dc42012-07-31 10:42:56 -0700344 self.waitUntilSettled()
345
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400346 # project-test2, project-merge for B
347 self.assertEqual(len(self.builds), 2)
348 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 4)
James E. Blaird466dc42012-07-31 10:42:56 -0700349
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700350 self.worker.hold_jobs_in_build = False
351 self.worker.release()
James E. Blaird466dc42012-07-31 10:42:56 -0700352 self.waitUntilSettled()
353
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400354 self.assertEqual(len(self.builds), 0)
355 self.assertEqual(len(self.history), 15)
356 self.assertEqual(A.data['status'], 'NEW')
357 self.assertEqual(B.data['status'], 'MERGED')
358 self.assertEqual(C.data['status'], 'MERGED')
359 self.assertEqual(A.reported, 2)
360 self.assertEqual(B.reported, 2)
361 self.assertEqual(C.reported, 2)
James E. Blaird466dc42012-07-31 10:42:56 -0700362
James E. Blair0aac4872013-08-23 14:02:38 -0700363 def test_failed_change_in_middle(self):
364 "Test a failed change in the middle of the queue"
365
366 self.worker.hold_jobs_in_build = True
367 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
368 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
369 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
370 A.addApproval('CRVW', 2)
371 B.addApproval('CRVW', 2)
372 C.addApproval('CRVW', 2)
373
374 self.worker.addFailTest('project-test1', B)
375
376 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
377 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
378 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
379
380 self.waitUntilSettled()
381
382 self.worker.release('.*-merge')
383 self.waitUntilSettled()
384 self.worker.release('.*-merge')
385 self.waitUntilSettled()
386 self.worker.release('.*-merge')
387 self.waitUntilSettled()
388
389 self.assertEqual(len(self.builds), 6)
390 self.assertEqual(self.builds[0].name, 'project-test1')
391 self.assertEqual(self.builds[1].name, 'project-test2')
392 self.assertEqual(self.builds[2].name, 'project-test1')
393 self.assertEqual(self.builds[3].name, 'project-test2')
394 self.assertEqual(self.builds[4].name, 'project-test1')
395 self.assertEqual(self.builds[5].name, 'project-test2')
396
397 self.release(self.builds[2])
398 self.waitUntilSettled()
399
James E. Blair972e3c72013-08-29 12:04:55 -0700400 # project-test1 and project-test2 for A
401 # project-test2 for B
402 # project-merge for C (without B)
403 self.assertEqual(len(self.builds), 4)
James E. Blair0aac4872013-08-23 14:02:38 -0700404 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 2)
405
James E. Blair972e3c72013-08-29 12:04:55 -0700406 self.worker.release('.*-merge')
407 self.waitUntilSettled()
408
409 # project-test1 and project-test2 for A
410 # project-test2 for B
411 # project-test1 and project-test2 for C
412 self.assertEqual(len(self.builds), 5)
413
James E. Blair0aac4872013-08-23 14:02:38 -0700414 items = self.sched.layout.pipelines['gate'].getAllItems()
415 builds = items[0].current_build_set.getBuilds()
416 self.assertEqual(self.countJobResults(builds, 'SUCCESS'), 1)
417 self.assertEqual(self.countJobResults(builds, None), 2)
418 builds = items[1].current_build_set.getBuilds()
419 self.assertEqual(self.countJobResults(builds, 'SUCCESS'), 1)
420 self.assertEqual(self.countJobResults(builds, 'FAILURE'), 1)
421 self.assertEqual(self.countJobResults(builds, None), 1)
422 builds = items[2].current_build_set.getBuilds()
423 self.assertEqual(self.countJobResults(builds, 'SUCCESS'), 1)
James E. Blair972e3c72013-08-29 12:04:55 -0700424 self.assertEqual(self.countJobResults(builds, None), 2)
James E. Blair0aac4872013-08-23 14:02:38 -0700425
426 self.worker.hold_jobs_in_build = False
427 self.worker.release()
428 self.waitUntilSettled()
429
430 self.assertEqual(len(self.builds), 0)
431 self.assertEqual(len(self.history), 12)
432 self.assertEqual(A.data['status'], 'MERGED')
433 self.assertEqual(B.data['status'], 'NEW')
434 self.assertEqual(C.data['status'], 'MERGED')
435 self.assertEqual(A.reported, 2)
436 self.assertEqual(B.reported, 2)
437 self.assertEqual(C.reported, 2)
438
James E. Blaird466dc42012-07-31 10:42:56 -0700439 def test_failed_change_at_head_with_queue(self):
440 "Test that if a change at the head fails, queued jobs are canceled"
James E. Blaird466dc42012-07-31 10:42:56 -0700441
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700442 self.gearman_server.hold_jobs_in_queue = True
James E. Blaird466dc42012-07-31 10:42:56 -0700443 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
444 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
445 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
James E. Blair8c803f82012-07-31 16:25:42 -0700446 A.addApproval('CRVW', 2)
447 B.addApproval('CRVW', 2)
448 C.addApproval('CRVW', 2)
James E. Blaird466dc42012-07-31 10:42:56 -0700449
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700450 self.worker.addFailTest('project-test1', A)
James E. Blaird466dc42012-07-31 10:42:56 -0700451
452 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
453 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
454 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
455
456 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -0700457 queue = self.gearman_server.getQueue()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400458 self.assertEqual(len(self.builds), 0)
459 self.assertEqual(len(queue), 1)
460 self.assertEqual(queue[0].name, 'build:project-merge')
461 self.assertTrue(self.job_has_changes(queue[0], A))
James E. Blaird466dc42012-07-31 10:42:56 -0700462
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700463 self.gearman_server.release('.*-merge')
James E. Blaird466dc42012-07-31 10:42:56 -0700464 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700465 self.gearman_server.release('.*-merge')
James E. Blaird466dc42012-07-31 10:42:56 -0700466 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700467 self.gearman_server.release('.*-merge')
James E. Blaird466dc42012-07-31 10:42:56 -0700468 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -0700469 queue = self.gearman_server.getQueue()
James E. Blaird466dc42012-07-31 10:42:56 -0700470
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400471 self.assertEqual(len(self.builds), 0)
472 self.assertEqual(len(queue), 6)
473 self.assertEqual(queue[0].name, 'build:project-test1')
474 self.assertEqual(queue[1].name, 'build:project-test2')
475 self.assertEqual(queue[2].name, 'build:project-test1')
476 self.assertEqual(queue[3].name, 'build:project-test2')
477 self.assertEqual(queue[4].name, 'build:project-test1')
478 self.assertEqual(queue[5].name, 'build:project-test2')
James E. Blaird466dc42012-07-31 10:42:56 -0700479
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700480 self.release(queue[0])
James E. Blaird466dc42012-07-31 10:42:56 -0700481 self.waitUntilSettled()
482
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400483 self.assertEqual(len(self.builds), 0)
James E. Blair701c5b42013-06-06 09:34:59 -0700484 queue = self.gearman_server.getQueue()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400485 self.assertEqual(len(queue), 2) # project-test2, project-merge for B
486 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 0)
James E. Blaird466dc42012-07-31 10:42:56 -0700487
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700488 self.gearman_server.hold_jobs_in_queue = False
489 self.gearman_server.release()
James E. Blaird466dc42012-07-31 10:42:56 -0700490 self.waitUntilSettled()
491
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400492 self.assertEqual(len(self.builds), 0)
493 self.assertEqual(len(self.history), 11)
494 self.assertEqual(A.data['status'], 'NEW')
495 self.assertEqual(B.data['status'], 'MERGED')
496 self.assertEqual(C.data['status'], 'MERGED')
497 self.assertEqual(A.reported, 2)
498 self.assertEqual(B.reported, 2)
499 self.assertEqual(C.reported, 2)
James E. Blair8c803f82012-07-31 16:25:42 -0700500
James E. Blairfef71632013-09-23 11:15:47 -0700501 def test_two_failed_changes_at_head(self):
502 "Test that changes are reparented correctly if 2 fail at head"
503
504 self.worker.hold_jobs_in_build = True
505 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
506 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
507 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
508 A.addApproval('CRVW', 2)
509 B.addApproval('CRVW', 2)
510 C.addApproval('CRVW', 2)
511
512 self.worker.addFailTest('project-test1', A)
513 self.worker.addFailTest('project-test1', B)
514
515 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
516 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
517 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
518 self.waitUntilSettled()
519
520 self.worker.release('.*-merge')
521 self.waitUntilSettled()
522 self.worker.release('.*-merge')
523 self.waitUntilSettled()
524 self.worker.release('.*-merge')
525 self.waitUntilSettled()
526
527 self.assertEqual(len(self.builds), 6)
528 self.assertEqual(self.builds[0].name, 'project-test1')
529 self.assertEqual(self.builds[1].name, 'project-test2')
530 self.assertEqual(self.builds[2].name, 'project-test1')
531 self.assertEqual(self.builds[3].name, 'project-test2')
532 self.assertEqual(self.builds[4].name, 'project-test1')
533 self.assertEqual(self.builds[5].name, 'project-test2')
534
535 self.assertTrue(self.job_has_changes(self.builds[0], A))
536 self.assertTrue(self.job_has_changes(self.builds[2], A))
537 self.assertTrue(self.job_has_changes(self.builds[2], B))
538 self.assertTrue(self.job_has_changes(self.builds[4], A))
539 self.assertTrue(self.job_has_changes(self.builds[4], B))
540 self.assertTrue(self.job_has_changes(self.builds[4], C))
541
542 # Fail change B first
543 self.release(self.builds[2])
544 self.waitUntilSettled()
545
546 # restart of C after B failure
547 self.worker.release('.*-merge')
548 self.waitUntilSettled()
549
550 self.assertEqual(len(self.builds), 5)
551 self.assertEqual(self.builds[0].name, 'project-test1')
552 self.assertEqual(self.builds[1].name, 'project-test2')
553 self.assertEqual(self.builds[2].name, 'project-test2')
554 self.assertEqual(self.builds[3].name, 'project-test1')
555 self.assertEqual(self.builds[4].name, 'project-test2')
556
557 self.assertTrue(self.job_has_changes(self.builds[1], A))
558 self.assertTrue(self.job_has_changes(self.builds[2], A))
559 self.assertTrue(self.job_has_changes(self.builds[2], B))
560 self.assertTrue(self.job_has_changes(self.builds[4], A))
561 self.assertFalse(self.job_has_changes(self.builds[4], B))
562 self.assertTrue(self.job_has_changes(self.builds[4], C))
563
564 # Finish running all passing jobs for change A
565 self.release(self.builds[1])
566 self.waitUntilSettled()
567 # Fail and report change A
568 self.release(self.builds[0])
569 self.waitUntilSettled()
570
571 # restart of B,C after A failure
572 self.worker.release('.*-merge')
573 self.waitUntilSettled()
574 self.worker.release('.*-merge')
575 self.waitUntilSettled()
576
577 self.assertEqual(len(self.builds), 4)
578 self.assertEqual(self.builds[0].name, 'project-test1') # B
579 self.assertEqual(self.builds[1].name, 'project-test2') # B
580 self.assertEqual(self.builds[2].name, 'project-test1') # C
581 self.assertEqual(self.builds[3].name, 'project-test2') # C
582
583 self.assertFalse(self.job_has_changes(self.builds[1], A))
584 self.assertTrue(self.job_has_changes(self.builds[1], B))
585 self.assertFalse(self.job_has_changes(self.builds[1], C))
586
587 self.assertFalse(self.job_has_changes(self.builds[2], A))
588 # After A failed and B and C restarted, B should be back in
589 # C's tests because it has not failed yet.
590 self.assertTrue(self.job_has_changes(self.builds[2], B))
591 self.assertTrue(self.job_has_changes(self.builds[2], C))
592
593 self.worker.hold_jobs_in_build = False
594 self.worker.release()
595 self.waitUntilSettled()
596
597 self.assertEqual(len(self.builds), 0)
598 self.assertEqual(len(self.history), 21)
599 self.assertEqual(A.data['status'], 'NEW')
600 self.assertEqual(B.data['status'], 'NEW')
601 self.assertEqual(C.data['status'], 'MERGED')
602 self.assertEqual(A.reported, 2)
603 self.assertEqual(B.reported, 2)
604 self.assertEqual(C.reported, 2)
605
James E. Blair8c803f82012-07-31 16:25:42 -0700606 def test_patch_order(self):
607 "Test that dependent patches are tested in the right order"
608 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
609 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
610 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
611 A.addApproval('CRVW', 2)
612 B.addApproval('CRVW', 2)
613 C.addApproval('CRVW', 2)
614
615 M2 = self.fake_gerrit.addFakeChange('org/project', 'master', 'M2')
616 M1 = self.fake_gerrit.addFakeChange('org/project', 'master', 'M1')
617 M2.setMerged()
618 M1.setMerged()
619
620 # C -> B -> A -> M1 -> M2
621 # M2 is here to make sure it is never queried. If it is, it
622 # means zuul is walking down the entire history of merged
623 # changes.
624
625 C.setDependsOn(B, 1)
626 B.setDependsOn(A, 1)
627 A.setDependsOn(M1, 1)
628 M1.setDependsOn(M2, 1)
629
630 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
631
632 self.waitUntilSettled()
633
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400634 self.assertEqual(A.data['status'], 'NEW')
635 self.assertEqual(B.data['status'], 'NEW')
636 self.assertEqual(C.data['status'], 'NEW')
James E. Blair8c803f82012-07-31 16:25:42 -0700637
638 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
639 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
640
641 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400642 self.assertEqual(M2.queried, 0)
643 self.assertEqual(A.data['status'], 'MERGED')
644 self.assertEqual(B.data['status'], 'MERGED')
645 self.assertEqual(C.data['status'], 'MERGED')
646 self.assertEqual(A.reported, 2)
647 self.assertEqual(B.reported, 2)
648 self.assertEqual(C.reported, 2)
James E. Blair8c803f82012-07-31 16:25:42 -0700649
James E. Blair063672f2015-01-29 13:09:12 -0800650 def test_needed_changes_enqueue(self):
651 "Test that a needed change is enqueued ahead"
652 # A Given a git tree like this, if we enqueue
653 # / \ change C, we should walk up and down the tree
654 # B G and enqueue changes in the order ABCDEFG.
655 # /|\ This is also the order that you would get if
656 # *C E F you enqueued changes in the order ABCDEFG, so
657 # / the ordering is stable across re-enqueue events.
658 # D
659
660 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
661 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
662 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
663 D = self.fake_gerrit.addFakeChange('org/project', 'master', 'D')
664 E = self.fake_gerrit.addFakeChange('org/project', 'master', 'E')
665 F = self.fake_gerrit.addFakeChange('org/project', 'master', 'F')
666 G = self.fake_gerrit.addFakeChange('org/project', 'master', 'G')
667 B.setDependsOn(A, 1)
668 C.setDependsOn(B, 1)
669 D.setDependsOn(C, 1)
670 E.setDependsOn(B, 1)
671 F.setDependsOn(B, 1)
672 G.setDependsOn(A, 1)
673
674 A.addApproval('CRVW', 2)
675 B.addApproval('CRVW', 2)
676 C.addApproval('CRVW', 2)
677 D.addApproval('CRVW', 2)
678 E.addApproval('CRVW', 2)
679 F.addApproval('CRVW', 2)
680 G.addApproval('CRVW', 2)
681 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
682
683 self.waitUntilSettled()
684
685 self.assertEqual(A.data['status'], 'NEW')
686 self.assertEqual(B.data['status'], 'NEW')
687 self.assertEqual(C.data['status'], 'NEW')
688 self.assertEqual(D.data['status'], 'NEW')
689 self.assertEqual(E.data['status'], 'NEW')
690 self.assertEqual(F.data['status'], 'NEW')
691 self.assertEqual(G.data['status'], 'NEW')
692
693 # We're about to add approvals to changes without adding the
694 # triggering events to Zuul, so that we can be sure that it is
695 # enqueing the changes based on dependencies, not because of
696 # triggering events. Since it will have the changes cached
697 # already (without approvals), we need to clear the cache
698 # first.
699 source = self.sched.layout.pipelines['gate'].source
700 source.maintainCache([])
701
702 self.worker.hold_jobs_in_build = True
703 A.addApproval('APRV', 1)
704 B.addApproval('APRV', 1)
705 D.addApproval('APRV', 1)
706 E.addApproval('APRV', 1)
707 F.addApproval('APRV', 1)
708 G.addApproval('APRV', 1)
709 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
710
711 for x in range(8):
712 self.worker.release('.*-merge')
713 self.waitUntilSettled()
714 self.worker.hold_jobs_in_build = False
715 self.worker.release()
716 self.waitUntilSettled()
717
718 self.assertEqual(A.data['status'], 'MERGED')
719 self.assertEqual(B.data['status'], 'MERGED')
720 self.assertEqual(C.data['status'], 'MERGED')
721 self.assertEqual(D.data['status'], 'MERGED')
722 self.assertEqual(E.data['status'], 'MERGED')
723 self.assertEqual(F.data['status'], 'MERGED')
724 self.assertEqual(G.data['status'], 'MERGED')
725 self.assertEqual(A.reported, 2)
726 self.assertEqual(B.reported, 2)
727 self.assertEqual(C.reported, 2)
728 self.assertEqual(D.reported, 2)
729 self.assertEqual(E.reported, 2)
730 self.assertEqual(F.reported, 2)
731 self.assertEqual(G.reported, 2)
732 self.assertEqual(self.history[6].changes,
733 '1,1 2,1 3,1 4,1 5,1 6,1 7,1')
734
Joshua Hesketh850ccb62014-11-27 11:31:02 +1100735 def test_source_cache(self):
736 "Test that the source cache operates correctly"
James E. Blair0e933c52013-07-11 10:18:52 -0700737 self.worker.hold_jobs_in_build = True
738
739 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
740 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
741 X = self.fake_gerrit.addFakeChange('org/project', 'master', 'X')
742 A.addApproval('CRVW', 2)
743 B.addApproval('CRVW', 2)
744
745 M1 = self.fake_gerrit.addFakeChange('org/project', 'master', 'M1')
746 M1.setMerged()
747
748 B.setDependsOn(A, 1)
749 A.setDependsOn(M1, 1)
750
751 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
752 self.fake_gerrit.addEvent(X.getPatchsetCreatedEvent(1))
753
754 self.waitUntilSettled()
755
756 for build in self.builds:
757 if build.parameters['ZUUL_PIPELINE'] == 'check':
758 build.release()
759 self.waitUntilSettled()
760 for build in self.builds:
761 if build.parameters['ZUUL_PIPELINE'] == 'check':
762 build.release()
763 self.waitUntilSettled()
764
765 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
766 self.waitUntilSettled()
767
Joshua Hesketh352264b2015-08-11 23:42:08 +1000768 self.log.debug("len %s" % self.fake_gerrit._change_cache.keys())
James E. Blair0e933c52013-07-11 10:18:52 -0700769 # there should still be changes in the cache
Joshua Hesketh352264b2015-08-11 23:42:08 +1000770 self.assertNotEqual(len(self.fake_gerrit._change_cache.keys()), 0)
James E. Blair0e933c52013-07-11 10:18:52 -0700771
772 self.worker.hold_jobs_in_build = False
773 self.worker.release()
774 self.waitUntilSettled()
775
776 self.assertEqual(A.data['status'], 'MERGED')
777 self.assertEqual(B.data['status'], 'MERGED')
778 self.assertEqual(A.queried, 2) # Initial and isMerged
779 self.assertEqual(B.queried, 3) # Initial A, refresh from B, isMerged
780
James E. Blair8c803f82012-07-31 16:25:42 -0700781 def test_can_merge(self):
James E. Blair4886cc12012-07-18 15:39:41 -0700782 "Test whether a change is ready to merge"
James E. Blair8c803f82012-07-31 16:25:42 -0700783 # TODO: move to test_gerrit (this is a unit test!)
784 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
James E. Blairc0dedf82014-08-06 09:37:52 -0700785 source = self.sched.layout.pipelines['gate'].source
786 a = source._getChange(1, 2)
James E. Blaireff88162013-07-01 12:44:14 -0400787 mgr = self.sched.layout.pipelines['gate'].manager
James E. Blairc0dedf82014-08-06 09:37:52 -0700788 self.assertFalse(source.canMerge(a, mgr.getSubmitAllowNeeds()))
James E. Blair8c803f82012-07-31 16:25:42 -0700789
790 A.addApproval('CRVW', 2)
James E. Blairc0dedf82014-08-06 09:37:52 -0700791 a = source._getChange(1, 2, refresh=True)
792 self.assertFalse(source.canMerge(a, mgr.getSubmitAllowNeeds()))
James E. Blair8c803f82012-07-31 16:25:42 -0700793
794 A.addApproval('APRV', 1)
James E. Blairc0dedf82014-08-06 09:37:52 -0700795 a = source._getChange(1, 2, refresh=True)
796 self.assertTrue(source.canMerge(a, mgr.getSubmitAllowNeeds()))
797 source.maintainCache([])
James E. Blair4886cc12012-07-18 15:39:41 -0700798
799 def test_build_configuration(self):
800 "Test that zuul merges the right commits for testing"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700801
802 self.gearman_server.hold_jobs_in_queue = True
James E. Blair4886cc12012-07-18 15:39:41 -0700803 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
804 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
805 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
806 A.addApproval('CRVW', 2)
807 B.addApproval('CRVW', 2)
808 C.addApproval('CRVW', 2)
809 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
810 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
811 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
812 self.waitUntilSettled()
813
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700814 self.gearman_server.release('.*-merge')
James E. Blair4886cc12012-07-18 15:39:41 -0700815 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700816 self.gearman_server.release('.*-merge')
James E. Blair4886cc12012-07-18 15:39:41 -0700817 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700818 self.gearman_server.release('.*-merge')
James E. Blair4886cc12012-07-18 15:39:41 -0700819 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -0700820 queue = self.gearman_server.getQueue()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700821 ref = self.getParameter(queue[-1], 'ZUUL_REF')
822 self.gearman_server.hold_jobs_in_queue = False
823 self.gearman_server.release()
James E. Blair973721f2012-08-15 10:19:43 -0700824 self.waitUntilSettled()
James E. Blair4886cc12012-07-18 15:39:41 -0700825
Monty Taylorbc758832013-06-17 17:22:42 -0400826 path = os.path.join(self.git_root, "org/project")
James E. Blair4886cc12012-07-18 15:39:41 -0700827 repo = git.Repo(path)
828 repo_messages = [c.message.strip() for c in repo.iter_commits(ref)]
829 repo_messages.reverse()
James E. Blair4886cc12012-07-18 15:39:41 -0700830 correct_messages = ['initial commit', 'A-1', 'B-1', 'C-1']
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400831 self.assertEqual(repo_messages, correct_messages)
James E. Blair973721f2012-08-15 10:19:43 -0700832
833 def test_build_configuration_conflict(self):
834 "Test that merge conflicts are handled"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700835
836 self.gearman_server.hold_jobs_in_queue = True
James E. Blair6736beb2013-07-11 15:18:15 -0700837 A = self.fake_gerrit.addFakeChange('org/conflict-project',
838 'master', 'A')
James E. Blair973721f2012-08-15 10:19:43 -0700839 A.addPatchset(['conflict'])
James E. Blair6736beb2013-07-11 15:18:15 -0700840 B = self.fake_gerrit.addFakeChange('org/conflict-project',
841 'master', 'B')
James E. Blair973721f2012-08-15 10:19:43 -0700842 B.addPatchset(['conflict'])
James E. Blair6736beb2013-07-11 15:18:15 -0700843 C = self.fake_gerrit.addFakeChange('org/conflict-project',
844 'master', 'C')
James E. Blair973721f2012-08-15 10:19:43 -0700845 A.addApproval('CRVW', 2)
846 B.addApproval('CRVW', 2)
847 C.addApproval('CRVW', 2)
848 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
849 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
850 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
851 self.waitUntilSettled()
852
James E. Blair6736beb2013-07-11 15:18:15 -0700853 self.assertEqual(A.reported, 1)
854 self.assertEqual(B.reported, 1)
855 self.assertEqual(C.reported, 1)
856
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700857 self.gearman_server.release('.*-merge')
James E. Blair973721f2012-08-15 10:19:43 -0700858 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700859 self.gearman_server.release('.*-merge')
James E. Blair973721f2012-08-15 10:19:43 -0700860 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700861 self.gearman_server.release('.*-merge')
James E. Blair973721f2012-08-15 10:19:43 -0700862 self.waitUntilSettled()
James E. Blair972e3c72013-08-29 12:04:55 -0700863
864 self.assertEqual(len(self.history), 2) # A and C merge jobs
865
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700866 self.gearman_server.hold_jobs_in_queue = False
867 self.gearman_server.release()
James E. Blair973721f2012-08-15 10:19:43 -0700868 self.waitUntilSettled()
869
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400870 self.assertEqual(A.data['status'], 'MERGED')
871 self.assertEqual(B.data['status'], 'NEW')
872 self.assertEqual(C.data['status'], 'MERGED')
873 self.assertEqual(A.reported, 2)
874 self.assertEqual(B.reported, 2)
875 self.assertEqual(C.reported, 2)
James E. Blair972e3c72013-08-29 12:04:55 -0700876 self.assertEqual(len(self.history), 6)
James E. Blair6736beb2013-07-11 15:18:15 -0700877
James E. Blairdaabed22012-08-15 15:38:57 -0700878 def test_post(self):
879 "Test that post jobs run"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700880
Zhongyue Luo5d556072012-09-21 02:00:47 +0900881 e = {
882 "type": "ref-updated",
883 "submitter": {
884 "name": "User Name",
885 },
886 "refUpdate": {
887 "oldRev": "90f173846e3af9154517b88543ffbd1691f31366",
888 "newRev": "d479a0bfcb34da57a31adb2a595c0cf687812543",
889 "refName": "master",
890 "project": "org/project",
891 }
892 }
James E. Blairdaabed22012-08-15 15:38:57 -0700893 self.fake_gerrit.addEvent(e)
894 self.waitUntilSettled()
895
Monty Taylor6bef8ef2013-06-02 08:17:12 -0400896 job_names = [x.name for x in self.history]
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400897 self.assertEqual(len(self.history), 1)
898 self.assertIn('project-post', job_names)
James E. Blairc6294a52012-08-17 10:19:48 -0700899
K Jonathan Harkerf95e7232015-04-29 13:33:16 -0700900 def test_post_ignore_deletes(self):
901 "Test that deleting refs does not trigger post jobs"
902
903 e = {
904 "type": "ref-updated",
905 "submitter": {
906 "name": "User Name",
907 },
908 "refUpdate": {
909 "oldRev": "90f173846e3af9154517b88543ffbd1691f31366",
910 "newRev": "0000000000000000000000000000000000000000",
911 "refName": "master",
912 "project": "org/project",
913 }
914 }
915 self.fake_gerrit.addEvent(e)
916 self.waitUntilSettled()
917
918 job_names = [x.name for x in self.history]
919 self.assertEqual(len(self.history), 0)
920 self.assertNotIn('project-post', job_names)
921
922 def test_post_ignore_deletes_negative(self):
923 "Test that deleting refs does trigger post jobs"
924
James E. Blairf84026c2015-12-08 16:11:46 -0800925 self.updateConfigLayout(
926 'tests/fixtures/layout-dont-ignore-deletes.yaml')
K Jonathan Harkerf95e7232015-04-29 13:33:16 -0700927 self.sched.reconfigure(self.config)
928
929 e = {
930 "type": "ref-updated",
931 "submitter": {
932 "name": "User Name",
933 },
934 "refUpdate": {
935 "oldRev": "90f173846e3af9154517b88543ffbd1691f31366",
936 "newRev": "0000000000000000000000000000000000000000",
937 "refName": "master",
938 "project": "org/project",
939 }
940 }
941 self.fake_gerrit.addEvent(e)
942 self.waitUntilSettled()
943
944 job_names = [x.name for x in self.history]
945 self.assertEqual(len(self.history), 1)
946 self.assertIn('project-post', job_names)
947
James E. Blairc6294a52012-08-17 10:19:48 -0700948 def test_build_configuration_branch(self):
949 "Test that the right commits are on alternate branches"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700950
951 self.gearman_server.hold_jobs_in_queue = True
James E. Blairc6294a52012-08-17 10:19:48 -0700952 A = self.fake_gerrit.addFakeChange('org/project', 'mp', 'A')
953 B = self.fake_gerrit.addFakeChange('org/project', 'mp', 'B')
954 C = self.fake_gerrit.addFakeChange('org/project', 'mp', 'C')
955 A.addApproval('CRVW', 2)
956 B.addApproval('CRVW', 2)
957 C.addApproval('CRVW', 2)
958 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
959 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
960 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
961 self.waitUntilSettled()
962
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700963 self.gearman_server.release('.*-merge')
James E. Blairc6294a52012-08-17 10:19:48 -0700964 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700965 self.gearman_server.release('.*-merge')
James E. Blairc6294a52012-08-17 10:19:48 -0700966 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700967 self.gearman_server.release('.*-merge')
James E. Blairc6294a52012-08-17 10:19:48 -0700968 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -0700969 queue = self.gearman_server.getQueue()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700970 ref = self.getParameter(queue[-1], 'ZUUL_REF')
971 self.gearman_server.hold_jobs_in_queue = False
972 self.gearman_server.release()
James E. Blairc6294a52012-08-17 10:19:48 -0700973 self.waitUntilSettled()
974
Monty Taylorbc758832013-06-17 17:22:42 -0400975 path = os.path.join(self.git_root, "org/project")
James E. Blairc6294a52012-08-17 10:19:48 -0700976 repo = git.Repo(path)
977 repo_messages = [c.message.strip() for c in repo.iter_commits(ref)]
978 repo_messages.reverse()
James E. Blairc6294a52012-08-17 10:19:48 -0700979 correct_messages = ['initial commit', 'mp commit', 'A-1', 'B-1', 'C-1']
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400980 self.assertEqual(repo_messages, correct_messages)
James E. Blairc6294a52012-08-17 10:19:48 -0700981
982 def test_build_configuration_branch_interaction(self):
983 "Test that switching between branches works"
984 self.test_build_configuration()
985 self.test_build_configuration_branch()
986 # C has been merged, undo that
Monty Taylorbc758832013-06-17 17:22:42 -0400987 path = os.path.join(self.upstream_root, "org/project")
James E. Blairc6294a52012-08-17 10:19:48 -0700988 repo = git.Repo(path)
989 repo.heads.master.commit = repo.commit('init')
990 self.test_build_configuration()
991
992 def test_build_configuration_multi_branch(self):
993 "Test that dependent changes on multiple branches are merged"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700994
995 self.gearman_server.hold_jobs_in_queue = True
James E. Blairc6294a52012-08-17 10:19:48 -0700996 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
997 B = self.fake_gerrit.addFakeChange('org/project', 'mp', 'B')
998 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
999 A.addApproval('CRVW', 2)
1000 B.addApproval('CRVW', 2)
1001 C.addApproval('CRVW', 2)
1002 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1003 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1004 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1005 self.waitUntilSettled()
James E. Blairbb1fe502014-03-04 10:15:06 -08001006 queue = self.gearman_server.getQueue()
1007 job_A = None
1008 for job in queue:
1009 if 'project-merge' in job.name:
1010 job_A = job
1011 ref_A = self.getParameter(job_A, 'ZUUL_REF')
1012 commit_A = self.getParameter(job_A, 'ZUUL_COMMIT')
1013 self.log.debug("Got Zuul ref for change A: %s" % ref_A)
1014 self.log.debug("Got Zuul commit for change A: %s" % commit_A)
James E. Blairc6294a52012-08-17 10:19:48 -07001015
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001016 self.gearman_server.release('.*-merge')
James E. Blairc6294a52012-08-17 10:19:48 -07001017 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -07001018 queue = self.gearman_server.getQueue()
James E. Blaird320d7e2013-07-30 16:36:20 -07001019 job_B = None
1020 for job in queue:
1021 if 'project-merge' in job.name:
1022 job_B = job
1023 ref_B = self.getParameter(job_B, 'ZUUL_REF')
James E. Blairbb1fe502014-03-04 10:15:06 -08001024 commit_B = self.getParameter(job_B, 'ZUUL_COMMIT')
James E. Blairf750aa02013-07-15 14:11:24 -07001025 self.log.debug("Got Zuul ref for change B: %s" % ref_B)
James E. Blairbb1fe502014-03-04 10:15:06 -08001026 self.log.debug("Got Zuul commit for change B: %s" % commit_B)
1027
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001028 self.gearman_server.release('.*-merge')
James E. Blairc6294a52012-08-17 10:19:48 -07001029 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -07001030 queue = self.gearman_server.getQueue()
James E. Blaird320d7e2013-07-30 16:36:20 -07001031 for job in queue:
1032 if 'project-merge' in job.name:
1033 job_C = job
1034 ref_C = self.getParameter(job_C, 'ZUUL_REF')
James E. Blairbb1fe502014-03-04 10:15:06 -08001035 commit_C = self.getParameter(job_C, 'ZUUL_COMMIT')
James E. Blairf750aa02013-07-15 14:11:24 -07001036 self.log.debug("Got Zuul ref for change C: %s" % ref_C)
James E. Blairbb1fe502014-03-04 10:15:06 -08001037 self.log.debug("Got Zuul commit for change C: %s" % commit_C)
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001038 self.gearman_server.hold_jobs_in_queue = False
1039 self.gearman_server.release()
James E. Blairc6294a52012-08-17 10:19:48 -07001040 self.waitUntilSettled()
1041
Monty Taylorbc758832013-06-17 17:22:42 -04001042 path = os.path.join(self.git_root, "org/project")
James E. Blairc6294a52012-08-17 10:19:48 -07001043 repo = git.Repo(path)
1044
1045 repo_messages = [c.message.strip()
James E. Blairf750aa02013-07-15 14:11:24 -07001046 for c in repo.iter_commits(ref_C)]
James E. Blairbb1fe502014-03-04 10:15:06 -08001047 repo_shas = [c.hexsha for c in repo.iter_commits(ref_C)]
James E. Blairc6294a52012-08-17 10:19:48 -07001048 repo_messages.reverse()
James E. Blairc6294a52012-08-17 10:19:48 -07001049 correct_messages = ['initial commit', 'A-1', 'C-1']
James E. Blairbb1fe502014-03-04 10:15:06 -08001050 # Ensure the right commits are in the history for this ref
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001051 self.assertEqual(repo_messages, correct_messages)
James E. Blairbb1fe502014-03-04 10:15:06 -08001052 # Ensure ZUUL_REF -> ZUUL_COMMIT
1053 self.assertEqual(repo_shas[0], commit_C)
James E. Blairc6294a52012-08-17 10:19:48 -07001054
1055 repo_messages = [c.message.strip()
James E. Blairf750aa02013-07-15 14:11:24 -07001056 for c in repo.iter_commits(ref_B)]
James E. Blairbb1fe502014-03-04 10:15:06 -08001057 repo_shas = [c.hexsha for c in repo.iter_commits(ref_B)]
James E. Blairc6294a52012-08-17 10:19:48 -07001058 repo_messages.reverse()
James E. Blairc6294a52012-08-17 10:19:48 -07001059 correct_messages = ['initial commit', 'mp commit', 'B-1']
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001060 self.assertEqual(repo_messages, correct_messages)
James E. Blairbb1fe502014-03-04 10:15:06 -08001061 self.assertEqual(repo_shas[0], commit_B)
1062
1063 repo_messages = [c.message.strip()
1064 for c in repo.iter_commits(ref_A)]
1065 repo_shas = [c.hexsha for c in repo.iter_commits(ref_A)]
1066 repo_messages.reverse()
1067 correct_messages = ['initial commit', 'A-1']
1068 self.assertEqual(repo_messages, correct_messages)
1069 self.assertEqual(repo_shas[0], commit_A)
1070
1071 self.assertNotEqual(ref_A, ref_B, ref_C)
1072 self.assertNotEqual(commit_A, commit_B, commit_C)
James E. Blair7f71c802012-08-22 13:04:32 -07001073
1074 def test_one_job_project(self):
1075 "Test that queueing works with one job"
1076 A = self.fake_gerrit.addFakeChange('org/one-job-project',
1077 'master', 'A')
1078 B = self.fake_gerrit.addFakeChange('org/one-job-project',
1079 'master', 'B')
1080 A.addApproval('CRVW', 2)
1081 B.addApproval('CRVW', 2)
1082 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1083 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1084 self.waitUntilSettled()
1085
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001086 self.assertEqual(A.data['status'], 'MERGED')
1087 self.assertEqual(A.reported, 2)
1088 self.assertEqual(B.data['status'], 'MERGED')
1089 self.assertEqual(B.reported, 2)
James E. Blaircaec0c52012-08-22 14:52:22 -07001090
Antoine Musso80edd5a2013-02-13 15:37:53 +01001091 def test_job_from_templates_launched(self):
1092 "Test whether a job generated via a template can be launched"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001093
Antoine Musso80edd5a2013-02-13 15:37:53 +01001094 A = self.fake_gerrit.addFakeChange(
1095 'org/templated-project', 'master', 'A')
1096 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1097 self.waitUntilSettled()
Antoine Musso80edd5a2013-02-13 15:37:53 +01001098
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001099 self.assertEqual(self.getJobFromHistory('project-test1').result,
1100 'SUCCESS')
1101 self.assertEqual(self.getJobFromHistory('project-test2').result,
1102 'SUCCESS')
Antoine Musso80edd5a2013-02-13 15:37:53 +01001103
James E. Blair3e98c022013-12-16 15:25:38 -08001104 def test_layered_templates(self):
1105 "Test whether a job generated via a template can be launched"
1106
1107 A = self.fake_gerrit.addFakeChange(
1108 'org/layered-project', 'master', 'A')
1109 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1110 self.waitUntilSettled()
1111
1112 self.assertEqual(self.getJobFromHistory('project-test1').result,
1113 'SUCCESS')
1114 self.assertEqual(self.getJobFromHistory('project-test2').result,
1115 'SUCCESS')
James E. Blairaea6cf62013-12-16 15:38:12 -08001116 self.assertEqual(self.getJobFromHistory('layered-project-test3'
1117 ).result, 'SUCCESS')
1118 self.assertEqual(self.getJobFromHistory('layered-project-test4'
1119 ).result, 'SUCCESS')
James E. Blair12a92b12014-03-26 11:54:53 -07001120 self.assertEqual(self.getJobFromHistory('layered-project-foo-test5'
1121 ).result, 'SUCCESS')
James E. Blair3e98c022013-12-16 15:25:38 -08001122 self.assertEqual(self.getJobFromHistory('project-test6').result,
1123 'SUCCESS')
1124
James E. Blaircaec0c52012-08-22 14:52:22 -07001125 def test_dependent_changes_dequeue(self):
1126 "Test that dependent patches are not needlessly tested"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001127
James E. Blaircaec0c52012-08-22 14:52:22 -07001128 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1129 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1130 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1131 A.addApproval('CRVW', 2)
1132 B.addApproval('CRVW', 2)
1133 C.addApproval('CRVW', 2)
1134
1135 M1 = self.fake_gerrit.addFakeChange('org/project', 'master', 'M1')
1136 M1.setMerged()
1137
1138 # C -> B -> A -> M1
1139
1140 C.setDependsOn(B, 1)
1141 B.setDependsOn(A, 1)
1142 A.setDependsOn(M1, 1)
1143
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001144 self.worker.addFailTest('project-merge', A)
James E. Blaircaec0c52012-08-22 14:52:22 -07001145
1146 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1147 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1148 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1149
1150 self.waitUntilSettled()
1151
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001152 self.assertEqual(A.data['status'], 'NEW')
1153 self.assertEqual(A.reported, 2)
1154 self.assertEqual(B.data['status'], 'NEW')
1155 self.assertEqual(B.reported, 2)
1156 self.assertEqual(C.data['status'], 'NEW')
1157 self.assertEqual(C.reported, 2)
1158 self.assertEqual(len(self.history), 1)
James E. Blairec590122012-08-22 15:19:31 -07001159
James E. Blair972e3c72013-08-29 12:04:55 -07001160 def test_failing_dependent_changes(self):
1161 "Test that failing dependent patches are taken out of stream"
1162 self.worker.hold_jobs_in_build = True
1163 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1164 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1165 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1166 D = self.fake_gerrit.addFakeChange('org/project', 'master', 'D')
1167 E = self.fake_gerrit.addFakeChange('org/project', 'master', 'E')
1168 A.addApproval('CRVW', 2)
1169 B.addApproval('CRVW', 2)
1170 C.addApproval('CRVW', 2)
1171 D.addApproval('CRVW', 2)
1172 E.addApproval('CRVW', 2)
1173
1174 # E, D -> C -> B, A
1175
1176 D.setDependsOn(C, 1)
1177 C.setDependsOn(B, 1)
1178
1179 self.worker.addFailTest('project-test1', B)
1180
1181 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1182 self.fake_gerrit.addEvent(D.addApproval('APRV', 1))
1183 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1184 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1185 self.fake_gerrit.addEvent(E.addApproval('APRV', 1))
1186
1187 self.waitUntilSettled()
1188 self.worker.release('.*-merge')
1189 self.waitUntilSettled()
1190 self.worker.release('.*-merge')
1191 self.waitUntilSettled()
1192 self.worker.release('.*-merge')
1193 self.waitUntilSettled()
1194 self.worker.release('.*-merge')
1195 self.waitUntilSettled()
1196 self.worker.release('.*-merge')
1197 self.waitUntilSettled()
1198
1199 self.worker.hold_jobs_in_build = False
1200 for build in self.builds:
1201 if build.parameters['ZUUL_CHANGE'] != '1':
1202 build.release()
1203 self.waitUntilSettled()
1204
1205 self.worker.release()
1206 self.waitUntilSettled()
1207
1208 self.assertEqual(A.data['status'], 'MERGED')
1209 self.assertEqual(A.reported, 2)
Jeremy Stanley10837132014-08-02 16:10:56 +00001210 self.assertIn('Build succeeded', A.messages[1])
James E. Blair972e3c72013-08-29 12:04:55 -07001211 self.assertEqual(B.data['status'], 'NEW')
1212 self.assertEqual(B.reported, 2)
Jeremy Stanley10837132014-08-02 16:10:56 +00001213 self.assertIn('Build failed', B.messages[1])
James E. Blair972e3c72013-08-29 12:04:55 -07001214 self.assertEqual(C.data['status'], 'NEW')
1215 self.assertEqual(C.reported, 2)
Jeremy Stanley10837132014-08-02 16:10:56 +00001216 self.assertIn('depends on a change', C.messages[1])
James E. Blair972e3c72013-08-29 12:04:55 -07001217 self.assertEqual(D.data['status'], 'NEW')
1218 self.assertEqual(D.reported, 2)
Jeremy Stanley10837132014-08-02 16:10:56 +00001219 self.assertIn('depends on a change', D.messages[1])
James E. Blair972e3c72013-08-29 12:04:55 -07001220 self.assertEqual(E.data['status'], 'MERGED')
1221 self.assertEqual(E.reported, 2)
Jeremy Stanley10837132014-08-02 16:10:56 +00001222 self.assertIn('Build succeeded', E.messages[1])
James E. Blair972e3c72013-08-29 12:04:55 -07001223 self.assertEqual(len(self.history), 18)
1224
James E. Blairec590122012-08-22 15:19:31 -07001225 def test_head_is_dequeued_once(self):
James E. Blair2fa50962013-01-30 21:50:41 -08001226 "Test that if a change at the head fails it is dequeued only once"
James E. Blairec590122012-08-22 15:19:31 -07001227 # If it's dequeued more than once, we should see extra
1228 # aborted jobs.
James E. Blairec590122012-08-22 15:19:31 -07001229
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001230 self.worker.hold_jobs_in_build = True
James E. Blairec590122012-08-22 15:19:31 -07001231 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
1232 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
1233 C = self.fake_gerrit.addFakeChange('org/project1', 'master', 'C')
1234 A.addApproval('CRVW', 2)
1235 B.addApproval('CRVW', 2)
1236 C.addApproval('CRVW', 2)
1237
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001238 self.worker.addFailTest('project1-test1', A)
1239 self.worker.addFailTest('project1-test2', A)
1240 self.worker.addFailTest('project1-project2-integration', A)
James E. Blairec590122012-08-22 15:19:31 -07001241
1242 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1243 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1244 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1245
1246 self.waitUntilSettled()
James E. Blairec590122012-08-22 15:19:31 -07001247
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001248 self.assertEqual(len(self.builds), 1)
1249 self.assertEqual(self.builds[0].name, 'project1-merge')
1250 self.assertTrue(self.job_has_changes(self.builds[0], A))
James E. Blairec590122012-08-22 15:19:31 -07001251
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001252 self.worker.release('.*-merge')
James E. Blairec590122012-08-22 15:19:31 -07001253 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001254 self.worker.release('.*-merge')
James E. Blairec590122012-08-22 15:19:31 -07001255 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001256 self.worker.release('.*-merge')
James E. Blairec590122012-08-22 15:19:31 -07001257 self.waitUntilSettled()
1258
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001259 self.assertEqual(len(self.builds), 9)
1260 self.assertEqual(self.builds[0].name, 'project1-test1')
1261 self.assertEqual(self.builds[1].name, 'project1-test2')
1262 self.assertEqual(self.builds[2].name, 'project1-project2-integration')
1263 self.assertEqual(self.builds[3].name, 'project1-test1')
1264 self.assertEqual(self.builds[4].name, 'project1-test2')
1265 self.assertEqual(self.builds[5].name, 'project1-project2-integration')
1266 self.assertEqual(self.builds[6].name, 'project1-test1')
1267 self.assertEqual(self.builds[7].name, 'project1-test2')
1268 self.assertEqual(self.builds[8].name, 'project1-project2-integration')
James E. Blairec590122012-08-22 15:19:31 -07001269
Monty Taylor6bef8ef2013-06-02 08:17:12 -04001270 self.release(self.builds[0])
James E. Blairec590122012-08-22 15:19:31 -07001271 self.waitUntilSettled()
1272
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001273 self.assertEqual(len(self.builds), 3) # test2,integration, merge for B
1274 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 6)
James E. Blairec590122012-08-22 15:19:31 -07001275
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001276 self.worker.hold_jobs_in_build = False
1277 self.worker.release()
James E. Blairec590122012-08-22 15:19:31 -07001278 self.waitUntilSettled()
1279
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001280 self.assertEqual(len(self.builds), 0)
1281 self.assertEqual(len(self.history), 20)
James E. Blaircaec0c52012-08-22 14:52:22 -07001282
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001283 self.assertEqual(A.data['status'], 'NEW')
1284 self.assertEqual(B.data['status'], 'MERGED')
1285 self.assertEqual(C.data['status'], 'MERGED')
1286 self.assertEqual(A.reported, 2)
1287 self.assertEqual(B.reported, 2)
1288 self.assertEqual(C.reported, 2)
James E. Blair4ec821f2012-08-23 15:28:28 -07001289
1290 def test_nonvoting_job(self):
1291 "Test that non-voting jobs don't vote."
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001292
James E. Blair4ec821f2012-08-23 15:28:28 -07001293 A = self.fake_gerrit.addFakeChange('org/nonvoting-project',
1294 'master', 'A')
1295 A.addApproval('CRVW', 2)
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001296 self.worker.addFailTest('nonvoting-project-test2', A)
James E. Blair4ec821f2012-08-23 15:28:28 -07001297 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1298
1299 self.waitUntilSettled()
James E. Blair4ec821f2012-08-23 15:28:28 -07001300
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001301 self.assertEqual(A.data['status'], 'MERGED')
1302 self.assertEqual(A.reported, 2)
1303 self.assertEqual(
1304 self.getJobFromHistory('nonvoting-project-merge').result,
1305 'SUCCESS')
1306 self.assertEqual(
1307 self.getJobFromHistory('nonvoting-project-test1').result,
1308 'SUCCESS')
1309 self.assertEqual(
1310 self.getJobFromHistory('nonvoting-project-test2').result,
1311 'FAILURE')
James E. Blaire0487072012-08-29 17:38:31 -07001312
James E. Blair5821bd92015-09-16 08:48:15 -07001313 for build in self.builds:
1314 self.assertEqual(build.parameters['ZUUL_VOTING'], '0')
1315
James E. Blaire0487072012-08-29 17:38:31 -07001316 def test_check_queue_success(self):
1317 "Test successful check queue jobs."
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001318
James E. Blaire0487072012-08-29 17:38:31 -07001319 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1320 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1321
1322 self.waitUntilSettled()
James E. Blaire0487072012-08-29 17:38:31 -07001323
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001324 self.assertEqual(A.data['status'], 'NEW')
1325 self.assertEqual(A.reported, 1)
1326 self.assertEqual(self.getJobFromHistory('project-merge').result,
1327 'SUCCESS')
1328 self.assertEqual(self.getJobFromHistory('project-test1').result,
1329 'SUCCESS')
1330 self.assertEqual(self.getJobFromHistory('project-test2').result,
1331 'SUCCESS')
James E. Blaire0487072012-08-29 17:38:31 -07001332
1333 def test_check_queue_failure(self):
1334 "Test failed check queue jobs."
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001335
James E. Blaire0487072012-08-29 17:38:31 -07001336 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001337 self.worker.addFailTest('project-test2', A)
James E. Blaire0487072012-08-29 17:38:31 -07001338 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1339
1340 self.waitUntilSettled()
James E. Blaire0487072012-08-29 17:38:31 -07001341
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001342 self.assertEqual(A.data['status'], 'NEW')
1343 self.assertEqual(A.reported, 1)
1344 self.assertEqual(self.getJobFromHistory('project-merge').result,
James E. Blair78e31b32013-07-09 09:11:34 -07001345 'SUCCESS')
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001346 self.assertEqual(self.getJobFromHistory('project-test1').result,
1347 'SUCCESS')
1348 self.assertEqual(self.getJobFromHistory('project-test2').result,
1349 'FAILURE')
James E. Blair127bc182012-08-28 15:55:15 -07001350
1351 def test_dependent_behind_dequeue(self):
1352 "test that dependent changes behind dequeued changes work"
1353 # This complicated test is a reproduction of a real life bug
1354 self.sched.reconfigure(self.config)
James E. Blair127bc182012-08-28 15:55:15 -07001355
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001356 self.worker.hold_jobs_in_build = True
James E. Blair127bc182012-08-28 15:55:15 -07001357 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
1358 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
1359 C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
1360 D = self.fake_gerrit.addFakeChange('org/project2', 'master', 'D')
1361 E = self.fake_gerrit.addFakeChange('org/project2', 'master', 'E')
1362 F = self.fake_gerrit.addFakeChange('org/project3', 'master', 'F')
1363 D.setDependsOn(C, 1)
1364 E.setDependsOn(D, 1)
1365 A.addApproval('CRVW', 2)
1366 B.addApproval('CRVW', 2)
1367 C.addApproval('CRVW', 2)
1368 D.addApproval('CRVW', 2)
1369 E.addApproval('CRVW', 2)
1370 F.addApproval('CRVW', 2)
1371
1372 A.fail_merge = True
James E. Blair127bc182012-08-28 15:55:15 -07001373
1374 # Change object re-use in the gerrit trigger is hidden if
1375 # changes are added in quick succession; waiting makes it more
1376 # like real life.
1377 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1378 self.waitUntilSettled()
1379 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1380 self.waitUntilSettled()
1381
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001382 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001383 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001384 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001385 self.waitUntilSettled()
1386
1387 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1388 self.waitUntilSettled()
1389 self.fake_gerrit.addEvent(D.addApproval('APRV', 1))
1390 self.waitUntilSettled()
1391 self.fake_gerrit.addEvent(E.addApproval('APRV', 1))
1392 self.waitUntilSettled()
1393 self.fake_gerrit.addEvent(F.addApproval('APRV', 1))
1394 self.waitUntilSettled()
1395
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001396 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001397 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001398 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001399 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001400 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001401 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001402 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001403 self.waitUntilSettled()
1404
1405 # all jobs running
James E. Blaire955e062012-10-08 09:49:03 -07001406
1407 # Grab pointers to the jobs we want to release before
1408 # releasing any, because list indexes may change as
1409 # the jobs complete.
Monty Taylor6bef8ef2013-06-02 08:17:12 -04001410 a, b, c = self.builds[:3]
James E. Blaire955e062012-10-08 09:49:03 -07001411 a.release()
1412 b.release()
1413 c.release()
James E. Blair127bc182012-08-28 15:55:15 -07001414 self.waitUntilSettled()
1415
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001416 self.worker.hold_jobs_in_build = False
1417 self.worker.release()
James E. Blair127bc182012-08-28 15:55:15 -07001418 self.waitUntilSettled()
1419
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001420 self.assertEqual(A.data['status'], 'NEW')
1421 self.assertEqual(B.data['status'], 'MERGED')
1422 self.assertEqual(C.data['status'], 'MERGED')
1423 self.assertEqual(D.data['status'], 'MERGED')
1424 self.assertEqual(E.data['status'], 'MERGED')
1425 self.assertEqual(F.data['status'], 'MERGED')
James E. Blair127bc182012-08-28 15:55:15 -07001426
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001427 self.assertEqual(A.reported, 2)
1428 self.assertEqual(B.reported, 2)
1429 self.assertEqual(C.reported, 2)
1430 self.assertEqual(D.reported, 2)
1431 self.assertEqual(E.reported, 2)
1432 self.assertEqual(F.reported, 2)
James E. Blair127bc182012-08-28 15:55:15 -07001433
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001434 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 15)
1435 self.assertEqual(len(self.history), 44)
James E. Blair05fed602012-09-07 12:45:24 -07001436
1437 def test_merger_repack(self):
1438 "Test that the merger works after a repack"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001439
James E. Blair05fed602012-09-07 12:45:24 -07001440 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1441 A.addApproval('CRVW', 2)
1442 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1443 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001444 self.assertEqual(self.getJobFromHistory('project-merge').result,
1445 'SUCCESS')
1446 self.assertEqual(self.getJobFromHistory('project-test1').result,
1447 'SUCCESS')
1448 self.assertEqual(self.getJobFromHistory('project-test2').result,
1449 'SUCCESS')
1450 self.assertEqual(A.data['status'], 'MERGED')
1451 self.assertEqual(A.reported, 2)
James E. Blair05fed602012-09-07 12:45:24 -07001452 self.assertEmptyQueues()
James E. Blair4ca985f2013-05-30 12:27:43 -07001453 self.worker.build_history = []
James E. Blair05fed602012-09-07 12:45:24 -07001454
Monty Taylorbc758832013-06-17 17:22:42 -04001455 path = os.path.join(self.git_root, "org/project")
1456 print repack_repo(path)
James E. Blair05fed602012-09-07 12:45:24 -07001457
1458 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1459 A.addApproval('CRVW', 2)
1460 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1461 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001462 self.assertEqual(self.getJobFromHistory('project-merge').result,
1463 'SUCCESS')
1464 self.assertEqual(self.getJobFromHistory('project-test1').result,
1465 'SUCCESS')
1466 self.assertEqual(self.getJobFromHistory('project-test2').result,
1467 'SUCCESS')
1468 self.assertEqual(A.data['status'], 'MERGED')
1469 self.assertEqual(A.reported, 2)
James E. Blair7ee88a22012-09-12 18:59:31 +02001470
James E. Blair4886f282012-11-15 09:27:33 -08001471 def test_merger_repack_large_change(self):
1472 "Test that the merger works with large changes after a repack"
1473 # https://bugs.launchpad.net/zuul/+bug/1078946
James E. Blairac2c3242014-01-24 13:38:51 -08001474 # This test assumes the repo is already cloned; make sure it is
Joshua Hesketh352264b2015-08-11 23:42:08 +10001475 url = self.fake_gerrit.getGitUrl(
James E. Blairac2c3242014-01-24 13:38:51 -08001476 self.sched.layout.projects['org/project1'])
James E. Blair4076e2b2014-01-28 12:42:20 -08001477 self.merge_server.merger.addProject('org/project1', url)
James E. Blair4886f282012-11-15 09:27:33 -08001478 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
1479 A.addPatchset(large=True)
Monty Taylorbc758832013-06-17 17:22:42 -04001480 path = os.path.join(self.upstream_root, "org/project1")
1481 print repack_repo(path)
1482 path = os.path.join(self.git_root, "org/project1")
1483 print repack_repo(path)
James E. Blair4886f282012-11-15 09:27:33 -08001484
1485 A.addApproval('CRVW', 2)
1486 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1487 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001488 self.assertEqual(self.getJobFromHistory('project1-merge').result,
1489 'SUCCESS')
1490 self.assertEqual(self.getJobFromHistory('project1-test1').result,
1491 'SUCCESS')
1492 self.assertEqual(self.getJobFromHistory('project1-test2').result,
1493 'SUCCESS')
1494 self.assertEqual(A.data['status'], 'MERGED')
1495 self.assertEqual(A.reported, 2)
James E. Blair4886f282012-11-15 09:27:33 -08001496
James E. Blair7ee88a22012-09-12 18:59:31 +02001497 def test_nonexistent_job(self):
1498 "Test launching a job that doesn't exist"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001499 # Set to the state immediately after a restart
1500 self.resetGearmanServer()
1501 self.launcher.negative_function_cache_ttl = 0
James E. Blair7ee88a22012-09-12 18:59:31 +02001502
1503 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1504 A.addApproval('CRVW', 2)
1505 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1506 # There may be a thread about to report a lost change
1507 while A.reported < 2:
1508 self.waitUntilSettled()
Monty Taylor6bef8ef2013-06-02 08:17:12 -04001509 job_names = [x.name for x in self.history]
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001510 self.assertFalse(job_names)
1511 self.assertEqual(A.data['status'], 'NEW')
1512 self.assertEqual(A.reported, 2)
James E. Blair7ee88a22012-09-12 18:59:31 +02001513 self.assertEmptyQueues()
1514
1515 # Make sure things still work:
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001516 self.registerJobs()
James E. Blair7ee88a22012-09-12 18:59:31 +02001517 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1518 A.addApproval('CRVW', 2)
1519 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1520 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001521 self.assertEqual(self.getJobFromHistory('project-merge').result,
1522 'SUCCESS')
1523 self.assertEqual(self.getJobFromHistory('project-test1').result,
1524 'SUCCESS')
1525 self.assertEqual(self.getJobFromHistory('project-test2').result,
1526 'SUCCESS')
1527 self.assertEqual(A.data['status'], 'MERGED')
1528 self.assertEqual(A.reported, 2)
James E. Blairf62d4282012-12-31 17:01:50 -08001529
1530 def test_single_nonexistent_post_job(self):
1531 "Test launching a single post job that doesn't exist"
James E. Blairf62d4282012-12-31 17:01:50 -08001532 e = {
1533 "type": "ref-updated",
1534 "submitter": {
1535 "name": "User Name",
1536 },
1537 "refUpdate": {
1538 "oldRev": "90f173846e3af9154517b88543ffbd1691f31366",
1539 "newRev": "d479a0bfcb34da57a31adb2a595c0cf687812543",
1540 "refName": "master",
1541 "project": "org/project",
1542 }
1543 }
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001544 # Set to the state immediately after a restart
1545 self.resetGearmanServer()
1546 self.launcher.negative_function_cache_ttl = 0
1547
James E. Blairf62d4282012-12-31 17:01:50 -08001548 self.fake_gerrit.addEvent(e)
1549 self.waitUntilSettled()
1550
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001551 self.assertEqual(len(self.history), 0)
James E. Blair2fa50962013-01-30 21:50:41 -08001552
1553 def test_new_patchset_dequeues_old(self):
1554 "Test that a new patchset causes the old to be dequeued"
1555 # D -> C (depends on B) -> B (depends on A) -> A -> M
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001556 self.worker.hold_jobs_in_build = True
James E. Blair2fa50962013-01-30 21:50:41 -08001557 M = self.fake_gerrit.addFakeChange('org/project', 'master', 'M')
1558 M.setMerged()
1559
1560 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1561 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1562 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1563 D = self.fake_gerrit.addFakeChange('org/project', 'master', 'D')
1564 A.addApproval('CRVW', 2)
1565 B.addApproval('CRVW', 2)
1566 C.addApproval('CRVW', 2)
1567 D.addApproval('CRVW', 2)
1568
1569 C.setDependsOn(B, 1)
1570 B.setDependsOn(A, 1)
1571 A.setDependsOn(M, 1)
1572
1573 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1574 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1575 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1576 self.fake_gerrit.addEvent(D.addApproval('APRV', 1))
1577 self.waitUntilSettled()
1578
1579 B.addPatchset()
1580 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(2))
1581 self.waitUntilSettled()
1582
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001583 self.worker.hold_jobs_in_build = False
1584 self.worker.release()
James E. Blair2fa50962013-01-30 21:50:41 -08001585 self.waitUntilSettled()
1586
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001587 self.assertEqual(A.data['status'], 'MERGED')
1588 self.assertEqual(A.reported, 2)
1589 self.assertEqual(B.data['status'], 'NEW')
1590 self.assertEqual(B.reported, 2)
1591 self.assertEqual(C.data['status'], 'NEW')
1592 self.assertEqual(C.reported, 2)
1593 self.assertEqual(D.data['status'], 'MERGED')
1594 self.assertEqual(D.reported, 2)
1595 self.assertEqual(len(self.history), 9) # 3 each for A, B, D.
James E. Blair2fa50962013-01-30 21:50:41 -08001596
James E. Blairba437362015-02-07 11:41:52 -08001597 def test_new_patchset_check(self):
1598 "Test a new patchset in check"
Antoine Mussobd86a312014-01-08 14:51:33 +01001599
1600 self.worker.hold_jobs_in_build = True
1601
1602 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
James E. Blairba437362015-02-07 11:41:52 -08001603 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1604 check_pipeline = self.sched.layout.pipelines['check']
1605
1606 # Add two git-dependent changes
1607 B.setDependsOn(A, 1)
1608 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1609 self.waitUntilSettled()
Antoine Mussobd86a312014-01-08 14:51:33 +01001610 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1611 self.waitUntilSettled()
James E. Blairba437362015-02-07 11:41:52 -08001612
1613 # A live item, and a non-live/live pair
1614 items = check_pipeline.getAllItems()
1615 self.assertEqual(len(items), 3)
1616
1617 self.assertEqual(items[0].change.number, '1')
1618 self.assertEqual(items[0].change.patchset, '1')
1619 self.assertFalse(items[0].live)
1620
1621 self.assertEqual(items[1].change.number, '2')
1622 self.assertEqual(items[1].change.patchset, '1')
1623 self.assertTrue(items[1].live)
1624
1625 self.assertEqual(items[2].change.number, '1')
1626 self.assertEqual(items[2].change.patchset, '1')
1627 self.assertTrue(items[2].live)
1628
1629 # Add a new patchset to A
1630 A.addPatchset()
1631 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
1632 self.waitUntilSettled()
1633
1634 # The live copy of A,1 should be gone, but the non-live and B
1635 # should continue, and we should have a new A,2
1636 items = check_pipeline.getAllItems()
1637 self.assertEqual(len(items), 3)
1638
1639 self.assertEqual(items[0].change.number, '1')
1640 self.assertEqual(items[0].change.patchset, '1')
1641 self.assertFalse(items[0].live)
1642
1643 self.assertEqual(items[1].change.number, '2')
1644 self.assertEqual(items[1].change.patchset, '1')
1645 self.assertTrue(items[1].live)
1646
1647 self.assertEqual(items[2].change.number, '1')
1648 self.assertEqual(items[2].change.patchset, '2')
1649 self.assertTrue(items[2].live)
1650
1651 # Add a new patchset to B
1652 B.addPatchset()
1653 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(2))
1654 self.waitUntilSettled()
1655
1656 # The live copy of B,1 should be gone, and it's non-live copy of A,1
1657 # but we should have a new B,2 (still based on A,1)
1658 items = check_pipeline.getAllItems()
1659 self.assertEqual(len(items), 3)
1660
1661 self.assertEqual(items[0].change.number, '1')
1662 self.assertEqual(items[0].change.patchset, '2')
1663 self.assertTrue(items[0].live)
1664
1665 self.assertEqual(items[1].change.number, '1')
1666 self.assertEqual(items[1].change.patchset, '1')
1667 self.assertFalse(items[1].live)
1668
1669 self.assertEqual(items[2].change.number, '2')
1670 self.assertEqual(items[2].change.patchset, '2')
1671 self.assertTrue(items[2].live)
1672
1673 self.builds[0].release()
1674 self.waitUntilSettled()
1675 self.builds[0].release()
1676 self.waitUntilSettled()
1677 self.worker.hold_jobs_in_build = False
1678 self.worker.release()
1679 self.waitUntilSettled()
1680
1681 self.assertEqual(A.reported, 1)
1682 self.assertEqual(B.reported, 1)
1683 self.assertEqual(self.history[0].result, 'ABORTED')
1684 self.assertEqual(self.history[0].changes, '1,1')
1685 self.assertEqual(self.history[1].result, 'ABORTED')
1686 self.assertEqual(self.history[1].changes, '1,1 2,1')
1687 self.assertEqual(self.history[2].result, 'SUCCESS')
1688 self.assertEqual(self.history[2].changes, '1,2')
1689 self.assertEqual(self.history[3].result, 'SUCCESS')
1690 self.assertEqual(self.history[3].changes, '1,1 2,2')
1691
1692 def test_abandoned_gate(self):
1693 "Test that an abandoned change is dequeued from gate"
1694
1695 self.worker.hold_jobs_in_build = True
1696
1697 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1698 A.addApproval('CRVW', 2)
1699 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1700 self.waitUntilSettled()
Antoine Mussobd86a312014-01-08 14:51:33 +01001701 self.assertEqual(len(self.builds), 1, "One job being built (on hold)")
1702 self.assertEqual(self.builds[0].name, 'project-merge')
1703
1704 self.fake_gerrit.addEvent(A.getChangeAbandonedEvent())
1705 self.waitUntilSettled()
1706
Antoine Mussobd86a312014-01-08 14:51:33 +01001707 self.worker.release('.*-merge')
1708 self.waitUntilSettled()
1709
1710 self.assertEqual(len(self.builds), 0, "No job running")
Antoine Mussobd86a312014-01-08 14:51:33 +01001711 self.assertEqual(len(self.history), 1, "Only one build in history")
1712 self.assertEqual(self.history[0].result, 'ABORTED',
James E. Blairba437362015-02-07 11:41:52 -08001713 "Build should have been aborted")
1714 self.assertEqual(A.reported, 1,
1715 "Abandoned gate change should report only start")
1716
1717 def test_abandoned_check(self):
1718 "Test that an abandoned change is dequeued from check"
1719
1720 self.worker.hold_jobs_in_build = True
1721
1722 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1723 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1724 check_pipeline = self.sched.layout.pipelines['check']
1725
1726 # Add two git-dependent changes
1727 B.setDependsOn(A, 1)
1728 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1729 self.waitUntilSettled()
1730 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1731 self.waitUntilSettled()
1732 # A live item, and a non-live/live pair
1733 items = check_pipeline.getAllItems()
1734 self.assertEqual(len(items), 3)
1735
1736 self.assertEqual(items[0].change.number, '1')
1737 self.assertFalse(items[0].live)
1738
1739 self.assertEqual(items[1].change.number, '2')
1740 self.assertTrue(items[1].live)
1741
1742 self.assertEqual(items[2].change.number, '1')
1743 self.assertTrue(items[2].live)
1744
1745 # Abandon A
1746 self.fake_gerrit.addEvent(A.getChangeAbandonedEvent())
1747 self.waitUntilSettled()
1748
1749 # The live copy of A should be gone, but the non-live and B
1750 # should continue
1751 items = check_pipeline.getAllItems()
1752 self.assertEqual(len(items), 2)
1753
1754 self.assertEqual(items[0].change.number, '1')
1755 self.assertFalse(items[0].live)
1756
1757 self.assertEqual(items[1].change.number, '2')
1758 self.assertTrue(items[1].live)
1759
1760 self.worker.hold_jobs_in_build = False
1761 self.worker.release()
1762 self.waitUntilSettled()
1763
1764 self.assertEqual(len(self.history), 4)
1765 self.assertEqual(self.history[0].result, 'ABORTED',
Antoine Mussobd86a312014-01-08 14:51:33 +01001766 'Build should have been aborted')
1767 self.assertEqual(A.reported, 0, "Abandoned change should not report")
James E. Blairba437362015-02-07 11:41:52 -08001768 self.assertEqual(B.reported, 1, "Change should report")
Antoine Mussobd86a312014-01-08 14:51:33 +01001769
Steve Varnau7b78b312015-04-03 14:49:46 -07001770 def test_abandoned_not_timer(self):
1771 "Test that an abandoned change does not cancel timer jobs"
1772
1773 self.worker.hold_jobs_in_build = True
1774
1775 # Start timer trigger - also org/project
James E. Blairf84026c2015-12-08 16:11:46 -08001776 self.updateConfigLayout(
1777 'tests/fixtures/layout-idle.yaml')
Steve Varnau7b78b312015-04-03 14:49:46 -07001778 self.sched.reconfigure(self.config)
1779 self.registerJobs()
1780 # The pipeline triggers every second, so we should have seen
1781 # several by now.
1782 time.sleep(5)
1783 self.waitUntilSettled()
1784 # Stop queuing timer triggered jobs so that the assertions
1785 # below don't race against more jobs being queued.
James E. Blairf84026c2015-12-08 16:11:46 -08001786 self.updateConfigLayout(
1787 'tests/fixtures/layout-no-timer.yaml')
Steve Varnau7b78b312015-04-03 14:49:46 -07001788 self.sched.reconfigure(self.config)
1789 self.registerJobs()
1790 self.assertEqual(len(self.builds), 2, "Two timer jobs")
1791
1792 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1793 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1794 self.waitUntilSettled()
1795 self.assertEqual(len(self.builds), 3, "One change plus two timer jobs")
1796
1797 self.fake_gerrit.addEvent(A.getChangeAbandonedEvent())
1798 self.waitUntilSettled()
1799
1800 self.assertEqual(len(self.builds), 2, "Two timer jobs remain")
1801
1802 self.worker.release()
1803 self.waitUntilSettled()
1804
Arx Cruzb1b010d2013-10-28 19:49:59 -02001805 def test_zuul_url_return(self):
1806 "Test if ZUUL_URL is returning when zuul_url is set in zuul.conf"
James E. Blair4076e2b2014-01-28 12:42:20 -08001807 self.assertTrue(self.sched.config.has_option('merger', 'zuul_url'))
Arx Cruzb1b010d2013-10-28 19:49:59 -02001808 self.worker.hold_jobs_in_build = True
1809
1810 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1811 A.addApproval('CRVW', 2)
1812 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1813 self.waitUntilSettled()
1814
1815 self.assertEqual(len(self.builds), 1)
1816 for build in self.builds:
1817 self.assertTrue('ZUUL_URL' in build.parameters)
1818
1819 self.worker.hold_jobs_in_build = False
1820 self.worker.release()
1821 self.waitUntilSettled()
1822
James E. Blair2fa50962013-01-30 21:50:41 -08001823 def test_new_patchset_dequeues_old_on_head(self):
1824 "Test that a new patchset causes the old to be dequeued (at head)"
1825 # D -> C (depends on B) -> B (depends on A) -> A -> M
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001826 self.worker.hold_jobs_in_build = True
James E. Blair2fa50962013-01-30 21:50:41 -08001827 M = self.fake_gerrit.addFakeChange('org/project', 'master', 'M')
1828 M.setMerged()
1829 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1830 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1831 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1832 D = self.fake_gerrit.addFakeChange('org/project', 'master', 'D')
1833 A.addApproval('CRVW', 2)
1834 B.addApproval('CRVW', 2)
1835 C.addApproval('CRVW', 2)
1836 D.addApproval('CRVW', 2)
1837
1838 C.setDependsOn(B, 1)
1839 B.setDependsOn(A, 1)
1840 A.setDependsOn(M, 1)
1841
1842 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1843 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1844 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1845 self.fake_gerrit.addEvent(D.addApproval('APRV', 1))
1846 self.waitUntilSettled()
1847
1848 A.addPatchset()
1849 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
1850 self.waitUntilSettled()
1851
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001852 self.worker.hold_jobs_in_build = False
1853 self.worker.release()
James E. Blair2fa50962013-01-30 21:50:41 -08001854 self.waitUntilSettled()
1855
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001856 self.assertEqual(A.data['status'], 'NEW')
1857 self.assertEqual(A.reported, 2)
1858 self.assertEqual(B.data['status'], 'NEW')
1859 self.assertEqual(B.reported, 2)
1860 self.assertEqual(C.data['status'], 'NEW')
1861 self.assertEqual(C.reported, 2)
1862 self.assertEqual(D.data['status'], 'MERGED')
1863 self.assertEqual(D.reported, 2)
1864 self.assertEqual(len(self.history), 7)
James E. Blair2fa50962013-01-30 21:50:41 -08001865
1866 def test_new_patchset_dequeues_old_without_dependents(self):
1867 "Test that a new patchset causes only the old to be dequeued"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001868 self.worker.hold_jobs_in_build = True
James E. Blair2fa50962013-01-30 21:50:41 -08001869 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1870 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1871 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1872 A.addApproval('CRVW', 2)
1873 B.addApproval('CRVW', 2)
1874 C.addApproval('CRVW', 2)
1875
1876 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1877 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1878 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1879 self.waitUntilSettled()
1880
1881 B.addPatchset()
1882 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(2))
1883 self.waitUntilSettled()
1884
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001885 self.worker.hold_jobs_in_build = False
1886 self.worker.release()
James E. Blair2fa50962013-01-30 21:50:41 -08001887 self.waitUntilSettled()
1888
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001889 self.assertEqual(A.data['status'], 'MERGED')
1890 self.assertEqual(A.reported, 2)
1891 self.assertEqual(B.data['status'], 'NEW')
1892 self.assertEqual(B.reported, 2)
1893 self.assertEqual(C.data['status'], 'MERGED')
1894 self.assertEqual(C.reported, 2)
1895 self.assertEqual(len(self.history), 9)
James E. Blair2fa50962013-01-30 21:50:41 -08001896
1897 def test_new_patchset_dequeues_old_independent_queue(self):
1898 "Test that a new patchset causes the old to be dequeued (independent)"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001899 self.worker.hold_jobs_in_build = True
James E. Blair2fa50962013-01-30 21:50:41 -08001900 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1901 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1902 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1903 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1904 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1905 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
1906 self.waitUntilSettled()
1907
1908 B.addPatchset()
1909 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(2))
1910 self.waitUntilSettled()
1911
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001912 self.worker.hold_jobs_in_build = False
1913 self.worker.release()
James E. Blair2fa50962013-01-30 21:50:41 -08001914 self.waitUntilSettled()
1915
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001916 self.assertEqual(A.data['status'], 'NEW')
1917 self.assertEqual(A.reported, 1)
1918 self.assertEqual(B.data['status'], 'NEW')
1919 self.assertEqual(B.reported, 1)
1920 self.assertEqual(C.data['status'], 'NEW')
1921 self.assertEqual(C.reported, 1)
1922 self.assertEqual(len(self.history), 10)
1923 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 1)
James E. Blair7d0dedc2013-02-21 17:26:09 -08001924
James E. Blair18c64442014-03-18 10:14:45 -07001925 def test_noop_job(self):
1926 "Test that the internal noop job works"
1927 A = self.fake_gerrit.addFakeChange('org/noop-project', 'master', 'A')
1928 A.addApproval('CRVW', 2)
1929 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1930 self.waitUntilSettled()
1931
1932 self.assertEqual(len(self.gearman_server.getQueue()), 0)
1933 self.assertTrue(self.sched._areAllBuildsComplete())
1934 self.assertEqual(len(self.history), 0)
1935 self.assertEqual(A.data['status'], 'MERGED')
1936 self.assertEqual(A.reported, 2)
1937
Evgeny Antyshevd6e546c2015-06-11 15:13:57 +00001938 def test_no_job_project(self):
1939 "Test that reports with no jobs don't get sent"
1940 A = self.fake_gerrit.addFakeChange('org/no-jobs-project',
1941 'master', 'A')
1942 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1943 self.waitUntilSettled()
1944
1945 # Change wasn't reported to
1946 self.assertEqual(A.reported, False)
1947
1948 # Check queue is empty afterwards
1949 check_pipeline = self.sched.layout.pipelines['check']
1950 items = check_pipeline.getAllItems()
1951 self.assertEqual(len(items), 0)
1952
1953 self.assertEqual(len(self.history), 0)
1954
James E. Blair7d0dedc2013-02-21 17:26:09 -08001955 def test_zuul_refs(self):
1956 "Test that zuul refs exist and have the right changes"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001957 self.worker.hold_jobs_in_build = True
James E. Blair7d0dedc2013-02-21 17:26:09 -08001958 M1 = self.fake_gerrit.addFakeChange('org/project1', 'master', 'M1')
1959 M1.setMerged()
1960 M2 = self.fake_gerrit.addFakeChange('org/project2', 'master', 'M2')
1961 M2.setMerged()
1962
1963 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
1964 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
1965 C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
1966 D = self.fake_gerrit.addFakeChange('org/project2', 'master', 'D')
1967 A.addApproval('CRVW', 2)
1968 B.addApproval('CRVW', 2)
1969 C.addApproval('CRVW', 2)
1970 D.addApproval('CRVW', 2)
1971 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1972 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1973 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1974 self.fake_gerrit.addEvent(D.addApproval('APRV', 1))
1975
1976 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001977 self.worker.release('.*-merge')
James E. Blair7d0dedc2013-02-21 17:26:09 -08001978 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001979 self.worker.release('.*-merge')
James E. Blair7d0dedc2013-02-21 17:26:09 -08001980 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001981 self.worker.release('.*-merge')
James E. Blair7d0dedc2013-02-21 17:26:09 -08001982 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001983 self.worker.release('.*-merge')
James E. Blair7d0dedc2013-02-21 17:26:09 -08001984 self.waitUntilSettled()
1985
James E. Blair7d0dedc2013-02-21 17:26:09 -08001986 a_zref = b_zref = c_zref = d_zref = None
Monty Taylor6bef8ef2013-06-02 08:17:12 -04001987 for x in self.builds:
James E. Blair7d0dedc2013-02-21 17:26:09 -08001988 if x.parameters['ZUUL_CHANGE'] == '3':
1989 a_zref = x.parameters['ZUUL_REF']
1990 if x.parameters['ZUUL_CHANGE'] == '4':
1991 b_zref = x.parameters['ZUUL_REF']
1992 if x.parameters['ZUUL_CHANGE'] == '5':
1993 c_zref = x.parameters['ZUUL_REF']
1994 if x.parameters['ZUUL_CHANGE'] == '6':
1995 d_zref = x.parameters['ZUUL_REF']
1996
1997 # There are... four... refs.
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001998 self.assertIsNotNone(a_zref)
1999 self.assertIsNotNone(b_zref)
2000 self.assertIsNotNone(c_zref)
2001 self.assertIsNotNone(d_zref)
James E. Blair7d0dedc2013-02-21 17:26:09 -08002002
2003 # And they should all be different
2004 refs = set([a_zref, b_zref, c_zref, d_zref])
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002005 self.assertEqual(len(refs), 4)
James E. Blair7d0dedc2013-02-21 17:26:09 -08002006
2007 # a ref should have a, not b, and should not be in project2
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002008 self.assertTrue(self.ref_has_change(a_zref, A))
2009 self.assertFalse(self.ref_has_change(a_zref, B))
2010 self.assertFalse(self.ref_has_change(a_zref, M2))
James E. Blair7d0dedc2013-02-21 17:26:09 -08002011
2012 # b ref should have a and b, and should not be in project2
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002013 self.assertTrue(self.ref_has_change(b_zref, A))
2014 self.assertTrue(self.ref_has_change(b_zref, B))
2015 self.assertFalse(self.ref_has_change(b_zref, M2))
James E. Blair7d0dedc2013-02-21 17:26:09 -08002016
2017 # c ref should have a and b in 1, c in 2
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002018 self.assertTrue(self.ref_has_change(c_zref, A))
2019 self.assertTrue(self.ref_has_change(c_zref, B))
2020 self.assertTrue(self.ref_has_change(c_zref, C))
2021 self.assertFalse(self.ref_has_change(c_zref, D))
James E. Blair7d0dedc2013-02-21 17:26:09 -08002022
2023 # d ref should have a and b in 1, c and d in 2
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002024 self.assertTrue(self.ref_has_change(d_zref, A))
2025 self.assertTrue(self.ref_has_change(d_zref, B))
2026 self.assertTrue(self.ref_has_change(d_zref, C))
2027 self.assertTrue(self.ref_has_change(d_zref, D))
James E. Blair7d0dedc2013-02-21 17:26:09 -08002028
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002029 self.worker.hold_jobs_in_build = False
2030 self.worker.release()
James E. Blair7d0dedc2013-02-21 17:26:09 -08002031 self.waitUntilSettled()
2032
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002033 self.assertEqual(A.data['status'], 'MERGED')
2034 self.assertEqual(A.reported, 2)
2035 self.assertEqual(B.data['status'], 'MERGED')
2036 self.assertEqual(B.reported, 2)
2037 self.assertEqual(C.data['status'], 'MERGED')
2038 self.assertEqual(C.reported, 2)
2039 self.assertEqual(D.data['status'], 'MERGED')
2040 self.assertEqual(D.reported, 2)
James E. Blair70c71582013-03-06 08:50:50 -08002041
James E. Blair4a28a882013-08-23 15:17:33 -07002042 def test_rerun_on_error(self):
2043 "Test that if a worker fails to run a job, it is run again"
2044 self.worker.hold_jobs_in_build = True
2045 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2046 A.addApproval('CRVW', 2)
2047 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2048 self.waitUntilSettled()
2049
2050 self.builds[0].run_error = True
2051 self.worker.hold_jobs_in_build = False
2052 self.worker.release()
2053 self.waitUntilSettled()
2054 self.assertEqual(self.countJobResults(self.history, 'RUN_ERROR'), 1)
2055 self.assertEqual(self.countJobResults(self.history, 'SUCCESS'), 3)
2056
James E. Blair412e5582013-04-22 15:50:12 -07002057 def test_statsd(self):
2058 "Test each of the statsd methods used in the scheduler"
2059 import extras
2060 statsd = extras.try_import('statsd.statsd')
2061 statsd.incr('test-incr')
2062 statsd.timing('test-timing', 3)
Alex Gaynor813d39b2014-05-17 16:17:16 -07002063 statsd.gauge('test-gauge', 12)
James E. Blair412e5582013-04-22 15:50:12 -07002064 self.assertReportedStat('test-incr', '1|c')
2065 self.assertReportedStat('test-timing', '3|ms')
Alex Gaynor813d39b2014-05-17 16:17:16 -07002066 self.assertReportedStat('test-gauge', '12|g')
James E. Blair412e5582013-04-22 15:50:12 -07002067
James E. Blairdad52252014-02-07 16:59:17 -08002068 def test_stuck_job_cleanup(self):
2069 "Test that pending jobs are cleaned up if removed from layout"
James E. Blair18c64442014-03-18 10:14:45 -07002070 # This job won't be registered at startup because it is not in
2071 # the standard layout, but we need it to already be registerd
2072 # for when we reconfigure, as that is when Zuul will attempt
2073 # to run the new job.
2074 self.worker.registerFunction('build:gate-noop')
James E. Blairdad52252014-02-07 16:59:17 -08002075 self.gearman_server.hold_jobs_in_queue = True
2076 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2077 A.addApproval('CRVW', 2)
2078 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2079 self.waitUntilSettled()
2080 self.assertEqual(len(self.gearman_server.getQueue()), 1)
2081
James E. Blairf84026c2015-12-08 16:11:46 -08002082 self.updateConfigLayout(
2083 'tests/fixtures/layout-no-jobs.yaml')
James E. Blairdad52252014-02-07 16:59:17 -08002084 self.sched.reconfigure(self.config)
2085 self.waitUntilSettled()
2086
James E. Blair18c64442014-03-18 10:14:45 -07002087 self.gearman_server.release('gate-noop')
James E. Blairdad52252014-02-07 16:59:17 -08002088 self.waitUntilSettled()
2089 self.assertEqual(len(self.gearman_server.getQueue()), 0)
2090 self.assertTrue(self.sched._areAllBuildsComplete())
2091
2092 self.assertEqual(len(self.history), 1)
James E. Blair18c64442014-03-18 10:14:45 -07002093 self.assertEqual(self.history[0].name, 'gate-noop')
James E. Blairdad52252014-02-07 16:59:17 -08002094 self.assertEqual(self.history[0].result, 'SUCCESS')
2095
James E. Blair879dafb2015-07-17 14:04:49 -07002096 def test_file_head(self):
2097 # This is a regression test for an observed bug. A change
2098 # with a file named "HEAD" in the root directory of the repo
2099 # was processed by a merger. It then was unable to reset the
2100 # repo because of:
2101 # GitCommandError: 'git reset --hard HEAD' returned
2102 # with exit code 128
2103 # stderr: 'fatal: ambiguous argument 'HEAD': both revision
2104 # and filename
2105 # Use '--' to separate filenames from revisions'
2106
2107 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2108 A.addPatchset(['HEAD'])
2109 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2110
2111 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
2112 self.waitUntilSettled()
2113
2114 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2115 self.waitUntilSettled()
2116
2117 self.assertIn('Build succeeded', A.messages[0])
2118 self.assertIn('Build succeeded', B.messages[0])
2119
James E. Blair70c71582013-03-06 08:50:50 -08002120 def test_file_jobs(self):
2121 "Test that file jobs run only when appropriate"
2122 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2123 A.addPatchset(['pip-requires'])
2124 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2125 A.addApproval('CRVW', 2)
2126 B.addApproval('CRVW', 2)
2127 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2128 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2129 self.waitUntilSettled()
2130
Monty Taylor6bef8ef2013-06-02 08:17:12 -04002131 testfile_jobs = [x for x in self.history
James E. Blair70c71582013-03-06 08:50:50 -08002132 if x.name == 'project-testfile']
2133
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002134 self.assertEqual(len(testfile_jobs), 1)
2135 self.assertEqual(testfile_jobs[0].changes, '1,2')
2136 self.assertEqual(A.data['status'], 'MERGED')
2137 self.assertEqual(A.reported, 2)
2138 self.assertEqual(B.data['status'], 'MERGED')
2139 self.assertEqual(B.reported, 2)
James E. Blair3c5e5b52013-04-26 11:17:03 -07002140
Maru Newby3fe5f852015-01-13 04:22:14 +00002141 def _test_skip_if_jobs(self, branch, should_skip):
2142 "Test that jobs with a skip-if filter run only when appropriate"
James E. Blairf84026c2015-12-08 16:11:46 -08002143 self.updateConfigLayout(
2144 'tests/fixtures/layout-skip-if.yaml')
Maru Newby3fe5f852015-01-13 04:22:14 +00002145 self.sched.reconfigure(self.config)
2146 self.registerJobs()
2147
2148 change = self.fake_gerrit.addFakeChange('org/project',
2149 branch,
2150 'test skip-if')
2151 self.fake_gerrit.addEvent(change.getPatchsetCreatedEvent(1))
2152 self.waitUntilSettled()
2153
2154 tested_change_ids = [x.changes[0] for x in self.history
2155 if x.name == 'project-test-skip-if']
2156
2157 if should_skip:
2158 self.assertEqual([], tested_change_ids)
2159 else:
2160 self.assertIn(change.data['number'], tested_change_ids)
2161
2162 def test_skip_if_match_skips_job(self):
2163 self._test_skip_if_jobs(branch='master', should_skip=True)
2164
2165 def test_skip_if_no_match_runs_job(self):
2166 self._test_skip_if_jobs(branch='mp', should_skip=False)
2167
James E. Blair3c5e5b52013-04-26 11:17:03 -07002168 def test_test_config(self):
2169 "Test that we can test the config"
James E. Blairf84026c2015-12-08 16:11:46 -08002170 self.sched.testConfig(self.config.get('zuul', 'tenant_config'),
Joshua Hesketh352264b2015-08-11 23:42:08 +10002171 self.connections)
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002172
2173 def test_build_description(self):
2174 "Test that build descriptions update"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002175 self.worker.registerFunction('set_description:' +
2176 self.worker.worker_id)
2177
2178 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2179 A.addApproval('CRVW', 2)
2180 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2181 self.waitUntilSettled()
Monty Taylor6bef8ef2013-06-02 08:17:12 -04002182 desc = self.history[0].description
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002183 self.log.debug("Description: %s" % desc)
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002184 self.assertTrue(re.search("Branch.*master", desc))
2185 self.assertTrue(re.search("Pipeline.*gate", desc))
2186 self.assertTrue(re.search("project-merge.*SUCCESS", desc))
2187 self.assertTrue(re.search("project-test1.*SUCCESS", desc))
2188 self.assertTrue(re.search("project-test2.*SUCCESS", desc))
2189 self.assertTrue(re.search("Reported result.*SUCCESS", desc))
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002190
James E. Blairc8a1e052014-02-25 09:29:26 -08002191 def test_queue_names(self):
2192 "Test shared change queue names"
2193 project1 = self.sched.layout.projects['org/project1']
2194 project2 = self.sched.layout.projects['org/project2']
2195 q1 = self.sched.layout.pipelines['gate'].getQueue(project1)
2196 q2 = self.sched.layout.pipelines['gate'].getQueue(project2)
2197 self.assertEqual(q1.name, 'integration')
2198 self.assertEqual(q2.name, 'integration')
2199
James E. Blairf84026c2015-12-08 16:11:46 -08002200 self.updateConfigLayout(
2201 'tests/fixtures/layout-bad-queue.yaml')
James E. Blairc8a1e052014-02-25 09:29:26 -08002202 with testtools.ExpectedException(
2203 Exception, "More than one name assigned to change queue"):
2204 self.sched.reconfigure(self.config)
2205
James E. Blair64ed6f22013-07-10 14:07:23 -07002206 def test_queue_precedence(self):
2207 "Test that queue precedence works"
2208
2209 self.gearman_server.hold_jobs_in_queue = True
James E. Blair8de58bd2013-07-18 16:23:33 -07002210 self.worker.hold_jobs_in_build = True
James E. Blair64ed6f22013-07-10 14:07:23 -07002211 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2212 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2213 A.addApproval('CRVW', 2)
2214 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2215
2216 self.waitUntilSettled()
2217 self.gearman_server.hold_jobs_in_queue = False
2218 self.gearman_server.release()
2219 self.waitUntilSettled()
2220
James E. Blair8de58bd2013-07-18 16:23:33 -07002221 # Run one build at a time to ensure non-race order:
James E. Blairb8c16472015-05-05 14:55:26 -07002222 self.orderedRelease()
James E. Blair8de58bd2013-07-18 16:23:33 -07002223 self.worker.hold_jobs_in_build = False
2224 self.waitUntilSettled()
2225
James E. Blair64ed6f22013-07-10 14:07:23 -07002226 self.log.debug(self.history)
2227 self.assertEqual(self.history[0].pipeline, 'gate')
2228 self.assertEqual(self.history[1].pipeline, 'check')
2229 self.assertEqual(self.history[2].pipeline, 'gate')
2230 self.assertEqual(self.history[3].pipeline, 'gate')
2231 self.assertEqual(self.history[4].pipeline, 'check')
2232 self.assertEqual(self.history[5].pipeline, 'check')
2233
Clark Boylana5edbe42014-06-03 16:39:10 -07002234 def test_json_status(self):
James E. Blair1843a552013-07-03 14:19:52 -07002235 "Test that we can retrieve JSON status info"
2236 self.worker.hold_jobs_in_build = True
2237 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2238 A.addApproval('CRVW', 2)
2239 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2240 self.waitUntilSettled()
2241
2242 port = self.webapp.server.socket.getsockname()[1]
2243
Yuriy Taradaya6d452f2014-04-16 12:36:20 +04002244 req = urllib2.Request("http://localhost:%s/status.json" % port)
Yuriy Taradaya6d452f2014-04-16 12:36:20 +04002245 f = urllib2.urlopen(req)
Clark Boylanaa4f2e72014-06-03 21:22:40 -07002246 headers = f.info()
2247 self.assertIn('Content-Length', headers)
2248 self.assertIn('Content-Type', headers)
2249 self.assertEqual(headers['Content-Type'],
2250 'application/json; charset=UTF-8')
Timo Tijhof0ebd2932015-04-02 12:11:21 +01002251 self.assertIn('Access-Control-Allow-Origin', headers)
2252 self.assertIn('Cache-Control', headers)
Clark Boylanaa4f2e72014-06-03 21:22:40 -07002253 self.assertIn('Last-Modified', headers)
Timo Tijhof0ebd2932015-04-02 12:11:21 +01002254 self.assertIn('Expires', headers)
James E. Blair1843a552013-07-03 14:19:52 -07002255 data = f.read()
2256
2257 self.worker.hold_jobs_in_build = False
2258 self.worker.release()
2259 self.waitUntilSettled()
2260
2261 data = json.loads(data)
2262 status_jobs = set()
2263 for p in data['pipelines']:
2264 for q in p['change_queues']:
James E. Blairbfb8e042014-12-30 17:01:44 -08002265 if p['name'] in ['gate', 'conflict']:
Clark Boylanaf2476f2014-01-23 14:47:36 -08002266 self.assertEqual(q['window'], 20)
2267 else:
2268 self.assertEqual(q['window'], 0)
James E. Blair1843a552013-07-03 14:19:52 -07002269 for head in q['heads']:
2270 for change in head:
Clark Boylanaf2476f2014-01-23 14:47:36 -08002271 self.assertTrue(change['active'])
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002272 self.assertEqual(change['id'], '1,1')
James E. Blair1843a552013-07-03 14:19:52 -07002273 for job in change['jobs']:
2274 status_jobs.add(job['name'])
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002275 self.assertIn('project-merge', status_jobs)
2276 self.assertIn('project-test1', status_jobs)
2277 self.assertIn('project-test2', status_jobs)
James E. Blair1843a552013-07-03 14:19:52 -07002278
James E. Blairc3d428e2013-12-03 15:06:48 -08002279 def test_merging_queues(self):
2280 "Test that transitively-connected change queues are merged"
James E. Blairf84026c2015-12-08 16:11:46 -08002281 self.updateConfigLayout(
2282 'tests/fixtures/layout-merge-queues.yaml')
James E. Blairc3d428e2013-12-03 15:06:48 -08002283 self.sched.reconfigure(self.config)
2284 self.assertEqual(len(self.sched.layout.pipelines['gate'].queues), 1)
2285
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002286 def test_node_label(self):
2287 "Test that a job runs on a specific node label"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002288 self.worker.registerFunction('build:node-project-test1:debian')
2289
2290 A = self.fake_gerrit.addFakeChange('org/node-project', 'master', 'A')
2291 A.addApproval('CRVW', 2)
2292 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2293 self.waitUntilSettled()
James E. Blair4ca985f2013-05-30 12:27:43 -07002294
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002295 self.assertIsNone(self.getJobFromHistory('node-project-merge').node)
2296 self.assertEqual(self.getJobFromHistory('node-project-test1').node,
2297 'debian')
2298 self.assertIsNone(self.getJobFromHistory('node-project-test2').node)
James E. Blaircdccd972013-07-01 12:10:22 -07002299
2300 def test_live_reconfiguration(self):
2301 "Test that live reconfiguration works"
2302 self.worker.hold_jobs_in_build = True
2303 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2304 A.addApproval('CRVW', 2)
2305 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2306 self.waitUntilSettled()
2307
2308 self.sched.reconfigure(self.config)
2309
2310 self.worker.hold_jobs_in_build = False
2311 self.worker.release()
2312 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002313 self.assertEqual(self.getJobFromHistory('project-merge').result,
2314 'SUCCESS')
2315 self.assertEqual(self.getJobFromHistory('project-test1').result,
2316 'SUCCESS')
2317 self.assertEqual(self.getJobFromHistory('project-test2').result,
2318 'SUCCESS')
2319 self.assertEqual(A.data['status'], 'MERGED')
2320 self.assertEqual(A.reported, 2)
James E. Blair287c06d2013-07-24 10:39:30 -07002321
James E. Blair6bc782d2015-07-17 16:20:21 -07002322 def test_live_reconfiguration_merge_conflict(self):
2323 # A real-world bug: a change in a gate queue has a merge
2324 # conflict and a job is added to its project while it's
2325 # sitting in the queue. The job gets added to the change and
2326 # enqueued and the change gets stuck.
2327 self.worker.registerFunction('build:project-test3')
2328 self.worker.hold_jobs_in_build = True
2329
2330 # This change is fine. It's here to stop the queue long
2331 # enough for the next change to be subject to the
2332 # reconfiguration, as well as to provide a conflict for the
2333 # next change. This change will succeed and merge.
2334 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2335 A.addPatchset(['conflict'])
2336 A.addApproval('CRVW', 2)
James E. Blair6bc782d2015-07-17 16:20:21 -07002337
2338 # This change will be in merge conflict. During the
2339 # reconfiguration, we will add a job. We want to make sure
2340 # that doesn't cause it to get stuck.
2341 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2342 B.addPatchset(['conflict'])
2343 B.addApproval('CRVW', 2)
James E. Blair4eb21fa2015-07-27 14:56:47 -07002344
2345 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
James E. Blair6bc782d2015-07-17 16:20:21 -07002346 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2347
2348 self.waitUntilSettled()
2349
2350 # No jobs have run yet
2351 self.assertEqual(A.data['status'], 'NEW')
2352 self.assertEqual(A.reported, 1)
2353 self.assertEqual(B.data['status'], 'NEW')
2354 self.assertEqual(B.reported, 1)
2355 self.assertEqual(len(self.history), 0)
2356
2357 # Add the "project-test3" job.
James E. Blairf84026c2015-12-08 16:11:46 -08002358 self.updateConfigLayout(
2359 'tests/fixtures/layout-live-reconfiguration-add-job.yaml')
James E. Blair6bc782d2015-07-17 16:20:21 -07002360 self.sched.reconfigure(self.config)
2361 self.waitUntilSettled()
2362
2363 self.worker.hold_jobs_in_build = False
2364 self.worker.release()
2365 self.waitUntilSettled()
2366
2367 self.assertEqual(A.data['status'], 'MERGED')
2368 self.assertEqual(A.reported, 2)
2369 self.assertEqual(B.data['status'], 'NEW')
2370 self.assertEqual(B.reported, 2)
2371 self.assertEqual(self.getJobFromHistory('project-merge').result,
2372 'SUCCESS')
2373 self.assertEqual(self.getJobFromHistory('project-test1').result,
2374 'SUCCESS')
2375 self.assertEqual(self.getJobFromHistory('project-test2').result,
2376 'SUCCESS')
2377 self.assertEqual(self.getJobFromHistory('project-test3').result,
2378 'SUCCESS')
2379 self.assertEqual(len(self.history), 4)
2380
James E. Blair400e8fd2015-07-30 17:44:45 -07002381 def test_live_reconfiguration_failed_root(self):
James E. Blair6bc782d2015-07-17 16:20:21 -07002382 # An extrapolation of test_live_reconfiguration_merge_conflict
2383 # that tests a job added to a job tree with a failed root does
2384 # not run.
2385 self.worker.registerFunction('build:project-test3')
2386 self.worker.hold_jobs_in_build = True
2387
2388 # This change is fine. It's here to stop the queue long
2389 # enough for the next change to be subject to the
2390 # reconfiguration. This change will succeed and merge.
2391 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2392 A.addPatchset(['conflict'])
2393 A.addApproval('CRVW', 2)
2394 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2395 self.waitUntilSettled()
2396 self.worker.release('.*-merge')
2397 self.waitUntilSettled()
2398
2399 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2400 self.worker.addFailTest('project-merge', B)
2401 B.addApproval('CRVW', 2)
2402 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2403 self.waitUntilSettled()
2404
2405 self.worker.release('.*-merge')
2406 self.waitUntilSettled()
2407
2408 # Both -merge jobs have run, but no others.
2409 self.assertEqual(A.data['status'], 'NEW')
2410 self.assertEqual(A.reported, 1)
2411 self.assertEqual(B.data['status'], 'NEW')
2412 self.assertEqual(B.reported, 1)
2413 self.assertEqual(self.history[0].result, 'SUCCESS')
2414 self.assertEqual(self.history[0].name, 'project-merge')
2415 self.assertEqual(self.history[1].result, 'FAILURE')
2416 self.assertEqual(self.history[1].name, 'project-merge')
2417 self.assertEqual(len(self.history), 2)
2418
2419 # Add the "project-test3" job.
James E. Blairf84026c2015-12-08 16:11:46 -08002420 self.updateConfigLayout(
2421 'tests/fixtures/layout-live-reconfiguration-add-job.yaml')
James E. Blair6bc782d2015-07-17 16:20:21 -07002422 self.sched.reconfigure(self.config)
2423 self.waitUntilSettled()
2424
2425 self.worker.hold_jobs_in_build = False
2426 self.worker.release()
2427 self.waitUntilSettled()
2428
2429 self.assertEqual(A.data['status'], 'MERGED')
2430 self.assertEqual(A.reported, 2)
2431 self.assertEqual(B.data['status'], 'NEW')
2432 self.assertEqual(B.reported, 2)
2433 self.assertEqual(self.history[0].result, 'SUCCESS')
2434 self.assertEqual(self.history[0].name, 'project-merge')
2435 self.assertEqual(self.history[1].result, 'FAILURE')
2436 self.assertEqual(self.history[1].name, 'project-merge')
2437 self.assertEqual(self.history[2].result, 'SUCCESS')
2438 self.assertEqual(self.history[3].result, 'SUCCESS')
2439 self.assertEqual(self.history[4].result, 'SUCCESS')
2440 self.assertEqual(len(self.history), 5)
2441
James E. Blair400e8fd2015-07-30 17:44:45 -07002442 def test_live_reconfiguration_failed_job(self):
2443 # Test that a change with a removed failing job does not
2444 # disrupt reconfiguration. If a change has a failed job and
2445 # that job is removed during a reconfiguration, we observed a
2446 # bug where the code to re-set build statuses would run on
2447 # that build and raise an exception because the job no longer
2448 # existed.
2449 self.worker.hold_jobs_in_build = True
2450
2451 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2452
2453 # This change will fail and later be removed by the reconfiguration.
2454 self.worker.addFailTest('project-test1', A)
2455
2456 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2457 self.waitUntilSettled()
2458 self.worker.release('.*-merge')
2459 self.waitUntilSettled()
2460 self.worker.release('project-test1')
2461 self.waitUntilSettled()
2462
2463 self.assertEqual(A.data['status'], 'NEW')
2464 self.assertEqual(A.reported, 0)
2465
2466 self.assertEqual(self.getJobFromHistory('project-merge').result,
2467 'SUCCESS')
2468 self.assertEqual(self.getJobFromHistory('project-test1').result,
2469 'FAILURE')
2470 self.assertEqual(len(self.history), 2)
2471
2472 # Remove the test1 job.
James E. Blairf84026c2015-12-08 16:11:46 -08002473 self.updateConfigLayout(
2474 'tests/fixtures/layout-live-reconfiguration-failed-job.yaml')
James E. Blair400e8fd2015-07-30 17:44:45 -07002475 self.sched.reconfigure(self.config)
2476 self.waitUntilSettled()
2477
2478 self.worker.hold_jobs_in_build = False
2479 self.worker.release()
2480 self.waitUntilSettled()
2481
2482 self.assertEqual(self.getJobFromHistory('project-test2').result,
2483 'SUCCESS')
2484 self.assertEqual(self.getJobFromHistory('project-testfile').result,
2485 'SUCCESS')
2486 self.assertEqual(len(self.history), 4)
2487
2488 self.assertEqual(A.data['status'], 'NEW')
2489 self.assertEqual(A.reported, 1)
2490 self.assertIn('Build succeeded', A.messages[0])
2491 # Ensure the removed job was not included in the report.
2492 self.assertNotIn('project-test1', A.messages[0])
2493
James E. Blairfe707d12015-08-05 15:18:15 -07002494 def test_live_reconfiguration_shared_queue(self):
2495 # Test that a change with a failing job which was removed from
2496 # this project but otherwise still exists in the system does
2497 # not disrupt reconfiguration.
2498
2499 self.worker.hold_jobs_in_build = True
2500
2501 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
2502
2503 self.worker.addFailTest('project1-project2-integration', A)
2504
2505 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2506 self.waitUntilSettled()
2507 self.worker.release('.*-merge')
2508 self.waitUntilSettled()
2509 self.worker.release('project1-project2-integration')
2510 self.waitUntilSettled()
2511
2512 self.assertEqual(A.data['status'], 'NEW')
2513 self.assertEqual(A.reported, 0)
2514
2515 self.assertEqual(self.getJobFromHistory('project1-merge').result,
2516 'SUCCESS')
2517 self.assertEqual(self.getJobFromHistory(
2518 'project1-project2-integration').result, 'FAILURE')
2519 self.assertEqual(len(self.history), 2)
2520
2521 # Remove the integration job.
James E. Blairf84026c2015-12-08 16:11:46 -08002522 self.updateConfigLayout(
2523 'tests/fixtures/layout-live-reconfiguration-shared-queue.yaml')
James E. Blairfe707d12015-08-05 15:18:15 -07002524 self.sched.reconfigure(self.config)
2525 self.waitUntilSettled()
2526
2527 self.worker.hold_jobs_in_build = False
2528 self.worker.release()
2529 self.waitUntilSettled()
2530
2531 self.assertEqual(self.getJobFromHistory('project1-merge').result,
2532 'SUCCESS')
2533 self.assertEqual(self.getJobFromHistory('project1-test1').result,
2534 'SUCCESS')
2535 self.assertEqual(self.getJobFromHistory('project1-test2').result,
2536 'SUCCESS')
2537 self.assertEqual(self.getJobFromHistory(
2538 'project1-project2-integration').result, 'FAILURE')
2539 self.assertEqual(len(self.history), 4)
2540
2541 self.assertEqual(A.data['status'], 'NEW')
2542 self.assertEqual(A.reported, 1)
2543 self.assertIn('Build succeeded', A.messages[0])
2544 # Ensure the removed job was not included in the report.
2545 self.assertNotIn('project1-project2-integration', A.messages[0])
2546
Evgeny Antyshev0deaaad2015-08-03 20:22:56 +00002547 def test_live_reconfiguration_del_project(self):
2548 # Test project deletion from layout
2549 # while changes are enqueued
2550
2551 self.worker.hold_jobs_in_build = True
2552 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2553 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
2554 C = self.fake_gerrit.addFakeChange('org/project1', 'master', 'C')
2555
2556 # A Depends-On: B
2557 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
2558 A.subject, B.data['id'])
2559 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2560
2561 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2562 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
2563 self.waitUntilSettled()
2564 self.worker.release('.*-merge')
2565 self.waitUntilSettled()
2566 self.assertEqual(len(self.builds), 5)
2567
2568 # This layout defines only org/project, not org/project1
James E. Blairf84026c2015-12-08 16:11:46 -08002569 self.updateConfigLayout(
2570 'tests/fixtures/layout-live-reconfiguration-del-project.yaml')
Evgeny Antyshev0deaaad2015-08-03 20:22:56 +00002571 self.sched.reconfigure(self.config)
2572 self.waitUntilSettled()
2573
2574 # Builds for C aborted, builds for A succeed,
2575 # and have change B applied ahead
2576 job_c = self.getJobFromHistory('project1-test1')
2577 self.assertEqual(job_c.changes, '3,1')
2578 self.assertEqual(job_c.result, 'ABORTED')
2579
2580 self.worker.hold_jobs_in_build = False
2581 self.worker.release()
2582 self.waitUntilSettled()
2583
2584 self.assertEqual(self.getJobFromHistory('project-test1').changes,
2585 '2,1 1,1')
2586
2587 self.assertEqual(A.data['status'], 'NEW')
2588 self.assertEqual(B.data['status'], 'NEW')
2589 self.assertEqual(C.data['status'], 'NEW')
2590 self.assertEqual(A.reported, 1)
2591 self.assertEqual(B.reported, 0)
2592 self.assertEqual(C.reported, 0)
2593
2594 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 0)
2595 self.assertIn('Build succeeded', A.messages[0])
2596
James E. Blaire712d9f2013-07-31 11:40:11 -07002597 def test_live_reconfiguration_functions(self):
2598 "Test live reconfiguration with a custom function"
2599 self.worker.registerFunction('build:node-project-test1:debian')
2600 self.worker.registerFunction('build:node-project-test1:wheezy')
2601 A = self.fake_gerrit.addFakeChange('org/node-project', 'master', 'A')
2602 A.addApproval('CRVW', 2)
2603 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2604 self.waitUntilSettled()
2605
2606 self.assertIsNone(self.getJobFromHistory('node-project-merge').node)
2607 self.assertEqual(self.getJobFromHistory('node-project-test1').node,
2608 'debian')
2609 self.assertIsNone(self.getJobFromHistory('node-project-test2').node)
2610
James E. Blairf84026c2015-12-08 16:11:46 -08002611 self.updateConfigLayout(
2612 'tests/fixtures/layout-live-reconfiguration-functions.yaml')
James E. Blaire712d9f2013-07-31 11:40:11 -07002613 self.sched.reconfigure(self.config)
2614 self.worker.build_history = []
2615
2616 B = self.fake_gerrit.addFakeChange('org/node-project', 'master', 'B')
2617 B.addApproval('CRVW', 2)
2618 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2619 self.waitUntilSettled()
2620
2621 self.assertIsNone(self.getJobFromHistory('node-project-merge').node)
2622 self.assertEqual(self.getJobFromHistory('node-project-test1').node,
2623 'wheezy')
2624 self.assertIsNone(self.getJobFromHistory('node-project-test2').node)
2625
James E. Blair287c06d2013-07-24 10:39:30 -07002626 def test_delayed_repo_init(self):
James E. Blairf84026c2015-12-08 16:11:46 -08002627 self.updateConfigLayout(
2628 'tests/fixtures/layout-delayed-repo-init.yaml')
James E. Blair287c06d2013-07-24 10:39:30 -07002629 self.sched.reconfigure(self.config)
2630
2631 self.init_repo("org/new-project")
2632 A = self.fake_gerrit.addFakeChange('org/new-project', 'master', 'A')
2633
2634 A.addApproval('CRVW', 2)
2635 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2636 self.waitUntilSettled()
2637 self.assertEqual(self.getJobFromHistory('project-merge').result,
2638 'SUCCESS')
2639 self.assertEqual(self.getJobFromHistory('project-test1').result,
2640 'SUCCESS')
2641 self.assertEqual(self.getJobFromHistory('project-test2').result,
2642 'SUCCESS')
2643 self.assertEqual(A.data['status'], 'MERGED')
2644 self.assertEqual(A.reported, 2)
James E. Blair63bb0ef2013-07-29 17:14:51 -07002645
Clark Boylan6dbbc482013-10-18 10:57:31 -07002646 def test_repo_deleted(self):
James E. Blairf84026c2015-12-08 16:11:46 -08002647 self.updateConfigLayout(
2648 'tests/fixtures/layout-repo-deleted.yaml')
Clark Boylan6dbbc482013-10-18 10:57:31 -07002649 self.sched.reconfigure(self.config)
2650
2651 self.init_repo("org/delete-project")
2652 A = self.fake_gerrit.addFakeChange('org/delete-project', 'master', 'A')
2653
2654 A.addApproval('CRVW', 2)
2655 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2656 self.waitUntilSettled()
2657 self.assertEqual(self.getJobFromHistory('project-merge').result,
2658 'SUCCESS')
2659 self.assertEqual(self.getJobFromHistory('project-test1').result,
2660 'SUCCESS')
2661 self.assertEqual(self.getJobFromHistory('project-test2').result,
2662 'SUCCESS')
2663 self.assertEqual(A.data['status'], 'MERGED')
2664 self.assertEqual(A.reported, 2)
2665
2666 # Delete org/new-project zuul repo. Should be recloned.
2667 shutil.rmtree(os.path.join(self.git_root, "org/delete-project"))
2668
2669 B = self.fake_gerrit.addFakeChange('org/delete-project', 'master', 'B')
2670
2671 B.addApproval('CRVW', 2)
2672 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2673 self.waitUntilSettled()
2674 self.assertEqual(self.getJobFromHistory('project-merge').result,
2675 'SUCCESS')
2676 self.assertEqual(self.getJobFromHistory('project-test1').result,
2677 'SUCCESS')
2678 self.assertEqual(self.getJobFromHistory('project-test2').result,
2679 'SUCCESS')
2680 self.assertEqual(B.data['status'], 'MERGED')
2681 self.assertEqual(B.reported, 2)
2682
James E. Blair63bb0ef2013-07-29 17:14:51 -07002683 def test_timer(self):
2684 "Test that a periodic job is triggered"
2685 self.worker.hold_jobs_in_build = True
James E. Blairf84026c2015-12-08 16:11:46 -08002686 self.updateConfigLayout(
2687 'tests/fixtures/layout-timer.yaml')
James E. Blair63bb0ef2013-07-29 17:14:51 -07002688 self.sched.reconfigure(self.config)
2689 self.registerJobs()
2690
Clark Boylan3ee090a2014-04-03 20:55:09 -07002691 # The pipeline triggers every second, so we should have seen
2692 # several by now.
2693 time.sleep(5)
James E. Blair63bb0ef2013-07-29 17:14:51 -07002694 self.waitUntilSettled()
Clark Boylan3ee090a2014-04-03 20:55:09 -07002695
2696 self.assertEqual(len(self.builds), 2)
2697
James E. Blair63bb0ef2013-07-29 17:14:51 -07002698 port = self.webapp.server.socket.getsockname()[1]
2699
2700 f = urllib.urlopen("http://localhost:%s/status.json" % port)
2701 data = f.read()
2702
2703 self.worker.hold_jobs_in_build = False
Clark Boylan3ee090a2014-04-03 20:55:09 -07002704 # Stop queuing timer triggered jobs so that the assertions
2705 # below don't race against more jobs being queued.
James E. Blairf84026c2015-12-08 16:11:46 -08002706 self.updateConfigLayout(
2707 'tests/fixtures/layout-no-timer.yaml')
Clark Boylan3ee090a2014-04-03 20:55:09 -07002708 self.sched.reconfigure(self.config)
2709 self.registerJobs()
James E. Blair63bb0ef2013-07-29 17:14:51 -07002710 self.worker.release()
2711 self.waitUntilSettled()
2712
2713 self.assertEqual(self.getJobFromHistory(
2714 'project-bitrot-stable-old').result, 'SUCCESS')
2715 self.assertEqual(self.getJobFromHistory(
2716 'project-bitrot-stable-older').result, 'SUCCESS')
2717
2718 data = json.loads(data)
2719 status_jobs = set()
2720 for p in data['pipelines']:
2721 for q in p['change_queues']:
2722 for head in q['heads']:
2723 for change in head:
Alex Gaynorddb9ef32013-09-16 21:04:58 -07002724 self.assertEqual(change['id'], None)
James E. Blair63bb0ef2013-07-29 17:14:51 -07002725 for job in change['jobs']:
2726 status_jobs.add(job['name'])
2727 self.assertIn('project-bitrot-stable-old', status_jobs)
2728 self.assertIn('project-bitrot-stable-older', status_jobs)
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002729
James E. Blair4f6033c2014-03-27 15:49:09 -07002730 def test_idle(self):
2731 "Test that frequent periodic jobs work"
2732 self.worker.hold_jobs_in_build = True
James E. Blair4f6033c2014-03-27 15:49:09 -07002733
Clark Boylan3ee090a2014-04-03 20:55:09 -07002734 for x in range(1, 3):
2735 # Test that timer triggers periodic jobs even across
2736 # layout config reloads.
2737 # Start timer trigger
James E. Blairf84026c2015-12-08 16:11:46 -08002738 self.updateConfigLayout(
2739 'tests/fixtures/layout-idle.yaml')
Clark Boylan3ee090a2014-04-03 20:55:09 -07002740 self.sched.reconfigure(self.config)
2741 self.registerJobs()
James E. Blair4f6033c2014-03-27 15:49:09 -07002742
Clark Boylan3ee090a2014-04-03 20:55:09 -07002743 # The pipeline triggers every second, so we should have seen
2744 # several by now.
2745 time.sleep(5)
2746 self.waitUntilSettled()
2747
2748 # Stop queuing timer triggered jobs so that the assertions
2749 # below don't race against more jobs being queued.
James E. Blairf84026c2015-12-08 16:11:46 -08002750 self.updateConfigLayout(
2751 'tests/fixtures/layout-no-timer.yaml')
Clark Boylan3ee090a2014-04-03 20:55:09 -07002752 self.sched.reconfigure(self.config)
2753 self.registerJobs()
2754
2755 self.assertEqual(len(self.builds), 2)
2756 self.worker.release('.*')
2757 self.waitUntilSettled()
2758 self.assertEqual(len(self.builds), 0)
2759 self.assertEqual(len(self.history), x * 2)
James E. Blair4f6033c2014-03-27 15:49:09 -07002760
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002761 def test_check_smtp_pool(self):
James E. Blairf84026c2015-12-08 16:11:46 -08002762 self.updateConfigLayout(
2763 'tests/fixtures/layout-smtp.yaml')
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002764 self.sched.reconfigure(self.config)
2765
2766 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2767 self.waitUntilSettled()
2768
2769 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2770 self.waitUntilSettled()
2771
James E. Blairff80a2f2013-12-27 13:24:06 -08002772 self.assertEqual(len(self.smtp_messages), 2)
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002773
2774 # A.messages only holds what FakeGerrit places in it. Thus we
2775 # work on the knowledge of what the first message should be as
2776 # it is only configured to go to SMTP.
2777
2778 self.assertEqual('zuul@example.com',
James E. Blairff80a2f2013-12-27 13:24:06 -08002779 self.smtp_messages[0]['from_email'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002780 self.assertEqual(['you@example.com'],
James E. Blairff80a2f2013-12-27 13:24:06 -08002781 self.smtp_messages[0]['to_email'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002782 self.assertEqual('Starting check jobs.',
James E. Blairff80a2f2013-12-27 13:24:06 -08002783 self.smtp_messages[0]['body'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002784
2785 self.assertEqual('zuul_from@example.com',
James E. Blairff80a2f2013-12-27 13:24:06 -08002786 self.smtp_messages[1]['from_email'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002787 self.assertEqual(['alternative_me@example.com'],
James E. Blairff80a2f2013-12-27 13:24:06 -08002788 self.smtp_messages[1]['to_email'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002789 self.assertEqual(A.messages[0],
James E. Blairff80a2f2013-12-27 13:24:06 -08002790 self.smtp_messages[1]['body'])
James E. Blairad28e912013-11-27 10:43:22 -08002791
James E. Blaire5910202013-12-27 09:50:31 -08002792 def test_timer_smtp(self):
2793 "Test that a periodic job is triggered"
Clark Boylan3ee090a2014-04-03 20:55:09 -07002794 self.worker.hold_jobs_in_build = True
James E. Blairf84026c2015-12-08 16:11:46 -08002795 self.updateConfigLayout(
2796 'tests/fixtures/layout-timer-smtp.yaml')
James E. Blaire5910202013-12-27 09:50:31 -08002797 self.sched.reconfigure(self.config)
2798 self.registerJobs()
2799
Clark Boylan3ee090a2014-04-03 20:55:09 -07002800 # The pipeline triggers every second, so we should have seen
2801 # several by now.
2802 time.sleep(5)
James E. Blaire5910202013-12-27 09:50:31 -08002803 self.waitUntilSettled()
2804
Clark Boylan3ee090a2014-04-03 20:55:09 -07002805 self.assertEqual(len(self.builds), 2)
2806 self.worker.release('.*')
2807 self.waitUntilSettled()
2808 self.assertEqual(len(self.history), 2)
2809
James E. Blaire5910202013-12-27 09:50:31 -08002810 self.assertEqual(self.getJobFromHistory(
2811 'project-bitrot-stable-old').result, 'SUCCESS')
2812 self.assertEqual(self.getJobFromHistory(
2813 'project-bitrot-stable-older').result, 'SUCCESS')
2814
James E. Blairff80a2f2013-12-27 13:24:06 -08002815 self.assertEqual(len(self.smtp_messages), 1)
James E. Blaire5910202013-12-27 09:50:31 -08002816
2817 # A.messages only holds what FakeGerrit places in it. Thus we
2818 # work on the knowledge of what the first message should be as
2819 # it is only configured to go to SMTP.
2820
2821 self.assertEqual('zuul_from@example.com',
James E. Blairff80a2f2013-12-27 13:24:06 -08002822 self.smtp_messages[0]['from_email'])
James E. Blaire5910202013-12-27 09:50:31 -08002823 self.assertEqual(['alternative_me@example.com'],
James E. Blairff80a2f2013-12-27 13:24:06 -08002824 self.smtp_messages[0]['to_email'])
James E. Blaire5910202013-12-27 09:50:31 -08002825 self.assertIn('Subject: Periodic check for org/project succeeded',
James E. Blairff80a2f2013-12-27 13:24:06 -08002826 self.smtp_messages[0]['headers'])
James E. Blaire5910202013-12-27 09:50:31 -08002827
Clark Boylan3ee090a2014-04-03 20:55:09 -07002828 # Stop queuing timer triggered jobs and let any that may have
2829 # queued through so that end of test assertions pass.
James E. Blairf84026c2015-12-08 16:11:46 -08002830 self.updateConfigLayout(
2831 'tests/fixtures/layout-no-timer.yaml')
Clark Boylan3ee090a2014-04-03 20:55:09 -07002832 self.sched.reconfigure(self.config)
2833 self.registerJobs()
James E. Blairf8058972014-08-15 16:09:16 -07002834 self.waitUntilSettled()
Clark Boylan3ee090a2014-04-03 20:55:09 -07002835 self.worker.release('.*')
2836 self.waitUntilSettled()
2837
James E. Blair91e34592015-07-31 16:45:59 -07002838 def test_client_enqueue_change(self):
James E. Blairad28e912013-11-27 10:43:22 -08002839 "Test that the RPC client can enqueue a change"
2840 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2841 A.addApproval('CRVW', 2)
2842 A.addApproval('APRV', 1)
2843
2844 client = zuul.rpcclient.RPCClient('127.0.0.1',
2845 self.gearman_server.port)
2846 r = client.enqueue(pipeline='gate',
2847 project='org/project',
2848 trigger='gerrit',
James E. Blair36658cf2013-12-06 17:53:48 -08002849 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08002850 self.waitUntilSettled()
2851 self.assertEqual(self.getJobFromHistory('project-merge').result,
2852 'SUCCESS')
2853 self.assertEqual(self.getJobFromHistory('project-test1').result,
2854 'SUCCESS')
2855 self.assertEqual(self.getJobFromHistory('project-test2').result,
2856 'SUCCESS')
2857 self.assertEqual(A.data['status'], 'MERGED')
2858 self.assertEqual(A.reported, 2)
2859 self.assertEqual(r, True)
2860
James E. Blair91e34592015-07-31 16:45:59 -07002861 def test_client_enqueue_ref(self):
2862 "Test that the RPC client can enqueue a ref"
2863
2864 client = zuul.rpcclient.RPCClient('127.0.0.1',
2865 self.gearman_server.port)
2866 r = client.enqueue_ref(
2867 pipeline='post',
2868 project='org/project',
2869 trigger='gerrit',
2870 ref='master',
2871 oldrev='90f173846e3af9154517b88543ffbd1691f31366',
2872 newrev='d479a0bfcb34da57a31adb2a595c0cf687812543')
2873 self.waitUntilSettled()
2874 job_names = [x.name for x in self.history]
2875 self.assertEqual(len(self.history), 1)
2876 self.assertIn('project-post', job_names)
2877 self.assertEqual(r, True)
2878
James E. Blairad28e912013-11-27 10:43:22 -08002879 def test_client_enqueue_negative(self):
2880 "Test that the RPC client returns errors"
2881 client = zuul.rpcclient.RPCClient('127.0.0.1',
2882 self.gearman_server.port)
2883 with testtools.ExpectedException(zuul.rpcclient.RPCFailure,
2884 "Invalid project"):
2885 r = client.enqueue(pipeline='gate',
2886 project='project-does-not-exist',
2887 trigger='gerrit',
James E. Blair36658cf2013-12-06 17:53:48 -08002888 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08002889 client.shutdown()
2890 self.assertEqual(r, False)
2891
2892 with testtools.ExpectedException(zuul.rpcclient.RPCFailure,
2893 "Invalid pipeline"):
2894 r = client.enqueue(pipeline='pipeline-does-not-exist',
2895 project='org/project',
2896 trigger='gerrit',
James E. Blair36658cf2013-12-06 17:53:48 -08002897 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08002898 client.shutdown()
2899 self.assertEqual(r, False)
2900
2901 with testtools.ExpectedException(zuul.rpcclient.RPCFailure,
2902 "Invalid trigger"):
2903 r = client.enqueue(pipeline='gate',
2904 project='org/project',
2905 trigger='trigger-does-not-exist',
James E. Blair36658cf2013-12-06 17:53:48 -08002906 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08002907 client.shutdown()
2908 self.assertEqual(r, False)
2909
2910 with testtools.ExpectedException(zuul.rpcclient.RPCFailure,
2911 "Invalid change"):
2912 r = client.enqueue(pipeline='gate',
2913 project='org/project',
2914 trigger='gerrit',
James E. Blair36658cf2013-12-06 17:53:48 -08002915 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08002916 client.shutdown()
2917 self.assertEqual(r, False)
2918
2919 self.waitUntilSettled()
2920 self.assertEqual(len(self.history), 0)
2921 self.assertEqual(len(self.builds), 0)
James E. Blair36658cf2013-12-06 17:53:48 -08002922
2923 def test_client_promote(self):
2924 "Test that the RPC client can promote a change"
2925 self.worker.hold_jobs_in_build = True
2926 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2927 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2928 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
2929 A.addApproval('CRVW', 2)
2930 B.addApproval('CRVW', 2)
2931 C.addApproval('CRVW', 2)
2932
2933 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2934 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2935 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
2936
2937 self.waitUntilSettled()
2938
Sean Daguef39b9ca2014-01-10 21:34:35 -05002939 items = self.sched.layout.pipelines['gate'].getAllItems()
2940 enqueue_times = {}
2941 for item in items:
2942 enqueue_times[str(item.change)] = item.enqueue_time
2943
James E. Blair36658cf2013-12-06 17:53:48 -08002944 client = zuul.rpcclient.RPCClient('127.0.0.1',
2945 self.gearman_server.port)
2946 r = client.promote(pipeline='gate',
2947 change_ids=['2,1', '3,1'])
2948
Sean Daguef39b9ca2014-01-10 21:34:35 -05002949 # ensure that enqueue times are durable
2950 items = self.sched.layout.pipelines['gate'].getAllItems()
2951 for item in items:
2952 self.assertEqual(
2953 enqueue_times[str(item.change)], item.enqueue_time)
2954
James E. Blair78acec92014-02-06 07:11:32 -08002955 self.waitUntilSettled()
James E. Blair36658cf2013-12-06 17:53:48 -08002956 self.worker.release('.*-merge')
2957 self.waitUntilSettled()
2958 self.worker.release('.*-merge')
2959 self.waitUntilSettled()
2960 self.worker.release('.*-merge')
2961 self.waitUntilSettled()
2962
2963 self.assertEqual(len(self.builds), 6)
2964 self.assertEqual(self.builds[0].name, 'project-test1')
2965 self.assertEqual(self.builds[1].name, 'project-test2')
2966 self.assertEqual(self.builds[2].name, 'project-test1')
2967 self.assertEqual(self.builds[3].name, 'project-test2')
2968 self.assertEqual(self.builds[4].name, 'project-test1')
2969 self.assertEqual(self.builds[5].name, 'project-test2')
2970
2971 self.assertTrue(self.job_has_changes(self.builds[0], B))
2972 self.assertFalse(self.job_has_changes(self.builds[0], A))
2973 self.assertFalse(self.job_has_changes(self.builds[0], C))
2974
2975 self.assertTrue(self.job_has_changes(self.builds[2], B))
2976 self.assertTrue(self.job_has_changes(self.builds[2], C))
2977 self.assertFalse(self.job_has_changes(self.builds[2], A))
2978
2979 self.assertTrue(self.job_has_changes(self.builds[4], B))
2980 self.assertTrue(self.job_has_changes(self.builds[4], C))
2981 self.assertTrue(self.job_has_changes(self.builds[4], A))
2982
2983 self.worker.release()
2984 self.waitUntilSettled()
2985
2986 self.assertEqual(A.data['status'], 'MERGED')
2987 self.assertEqual(A.reported, 2)
2988 self.assertEqual(B.data['status'], 'MERGED')
2989 self.assertEqual(B.reported, 2)
2990 self.assertEqual(C.data['status'], 'MERGED')
2991 self.assertEqual(C.reported, 2)
2992
2993 client.shutdown()
2994 self.assertEqual(r, True)
2995
2996 def test_client_promote_dependent(self):
2997 "Test that the RPC client can promote a dependent change"
2998 # C (depends on B) -> B -> A ; then promote C to get:
2999 # A -> C (depends on B) -> B
3000 self.worker.hold_jobs_in_build = True
3001 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3002 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
3003 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
3004
3005 C.setDependsOn(B, 1)
3006
3007 A.addApproval('CRVW', 2)
3008 B.addApproval('CRVW', 2)
3009 C.addApproval('CRVW', 2)
3010
3011 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3012 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3013 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
3014
3015 self.waitUntilSettled()
3016
3017 client = zuul.rpcclient.RPCClient('127.0.0.1',
3018 self.gearman_server.port)
3019 r = client.promote(pipeline='gate',
3020 change_ids=['3,1'])
3021
James E. Blair78acec92014-02-06 07:11:32 -08003022 self.waitUntilSettled()
James E. Blair36658cf2013-12-06 17:53:48 -08003023 self.worker.release('.*-merge')
3024 self.waitUntilSettled()
3025 self.worker.release('.*-merge')
3026 self.waitUntilSettled()
3027 self.worker.release('.*-merge')
3028 self.waitUntilSettled()
3029
3030 self.assertEqual(len(self.builds), 6)
3031 self.assertEqual(self.builds[0].name, 'project-test1')
3032 self.assertEqual(self.builds[1].name, 'project-test2')
3033 self.assertEqual(self.builds[2].name, 'project-test1')
3034 self.assertEqual(self.builds[3].name, 'project-test2')
3035 self.assertEqual(self.builds[4].name, 'project-test1')
3036 self.assertEqual(self.builds[5].name, 'project-test2')
3037
3038 self.assertTrue(self.job_has_changes(self.builds[0], B))
3039 self.assertFalse(self.job_has_changes(self.builds[0], A))
3040 self.assertFalse(self.job_has_changes(self.builds[0], C))
3041
3042 self.assertTrue(self.job_has_changes(self.builds[2], B))
3043 self.assertTrue(self.job_has_changes(self.builds[2], C))
3044 self.assertFalse(self.job_has_changes(self.builds[2], A))
3045
3046 self.assertTrue(self.job_has_changes(self.builds[4], B))
3047 self.assertTrue(self.job_has_changes(self.builds[4], C))
3048 self.assertTrue(self.job_has_changes(self.builds[4], A))
3049
3050 self.worker.release()
3051 self.waitUntilSettled()
3052
3053 self.assertEqual(A.data['status'], 'MERGED')
3054 self.assertEqual(A.reported, 2)
3055 self.assertEqual(B.data['status'], 'MERGED')
3056 self.assertEqual(B.reported, 2)
3057 self.assertEqual(C.data['status'], 'MERGED')
3058 self.assertEqual(C.reported, 2)
3059
3060 client.shutdown()
3061 self.assertEqual(r, True)
3062
3063 def test_client_promote_negative(self):
3064 "Test that the RPC client returns errors for promotion"
3065 self.worker.hold_jobs_in_build = True
3066 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3067 A.addApproval('CRVW', 2)
3068 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3069 self.waitUntilSettled()
3070
3071 client = zuul.rpcclient.RPCClient('127.0.0.1',
3072 self.gearman_server.port)
3073
3074 with testtools.ExpectedException(zuul.rpcclient.RPCFailure):
3075 r = client.promote(pipeline='nonexistent',
3076 change_ids=['2,1', '3,1'])
3077 client.shutdown()
3078 self.assertEqual(r, False)
3079
3080 with testtools.ExpectedException(zuul.rpcclient.RPCFailure):
3081 r = client.promote(pipeline='gate',
3082 change_ids=['4,1'])
3083 client.shutdown()
3084 self.assertEqual(r, False)
3085
3086 self.worker.hold_jobs_in_build = False
3087 self.worker.release()
3088 self.waitUntilSettled()
Clark Boylan7603a372014-01-21 11:43:20 -08003089
3090 def test_queue_rate_limiting(self):
3091 "Test that DependentPipelines are rate limited with dep across window"
James E. Blairf84026c2015-12-08 16:11:46 -08003092 self.updateConfigLayout(
3093 'tests/fixtures/layout-rate-limit.yaml')
Clark Boylan7603a372014-01-21 11:43:20 -08003094 self.sched.reconfigure(self.config)
3095 self.worker.hold_jobs_in_build = True
3096 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3097 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
3098 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
3099
3100 C.setDependsOn(B, 1)
3101 self.worker.addFailTest('project-test1', A)
3102
3103 A.addApproval('CRVW', 2)
3104 B.addApproval('CRVW', 2)
3105 C.addApproval('CRVW', 2)
3106
3107 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3108 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3109 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
3110 self.waitUntilSettled()
3111
3112 # Only A and B will have their merge jobs queued because
3113 # window is 2.
3114 self.assertEqual(len(self.builds), 2)
3115 self.assertEqual(self.builds[0].name, 'project-merge')
3116 self.assertEqual(self.builds[1].name, 'project-merge')
3117
3118 self.worker.release('.*-merge')
3119 self.waitUntilSettled()
3120 self.worker.release('.*-merge')
3121 self.waitUntilSettled()
3122
3123 # Only A and B will have their test jobs queued because
3124 # window is 2.
3125 self.assertEqual(len(self.builds), 4)
3126 self.assertEqual(self.builds[0].name, 'project-test1')
3127 self.assertEqual(self.builds[1].name, 'project-test2')
3128 self.assertEqual(self.builds[2].name, 'project-test1')
3129 self.assertEqual(self.builds[3].name, 'project-test2')
3130
3131 self.worker.release('project-.*')
3132 self.waitUntilSettled()
3133
3134 queue = self.sched.layout.pipelines['gate'].queues[0]
3135 # A failed so window is reduced by 1 to 1.
3136 self.assertEqual(queue.window, 1)
3137 self.assertEqual(queue.window_floor, 1)
3138 self.assertEqual(A.data['status'], 'NEW')
3139
3140 # Gate is reset and only B's merge job is queued because
3141 # window shrunk to 1.
3142 self.assertEqual(len(self.builds), 1)
3143 self.assertEqual(self.builds[0].name, 'project-merge')
3144
3145 self.worker.release('.*-merge')
3146 self.waitUntilSettled()
3147
3148 # Only B's test jobs are queued because window is still 1.
3149 self.assertEqual(len(self.builds), 2)
3150 self.assertEqual(self.builds[0].name, 'project-test1')
3151 self.assertEqual(self.builds[1].name, 'project-test2')
3152
3153 self.worker.release('project-.*')
3154 self.waitUntilSettled()
3155
3156 # B was successfully merged so window is increased to 2.
3157 self.assertEqual(queue.window, 2)
3158 self.assertEqual(queue.window_floor, 1)
3159 self.assertEqual(B.data['status'], 'MERGED')
3160
3161 # Only C is left and its merge job is queued.
3162 self.assertEqual(len(self.builds), 1)
3163 self.assertEqual(self.builds[0].name, 'project-merge')
3164
3165 self.worker.release('.*-merge')
3166 self.waitUntilSettled()
3167
3168 # After successful merge job the test jobs for C are queued.
3169 self.assertEqual(len(self.builds), 2)
3170 self.assertEqual(self.builds[0].name, 'project-test1')
3171 self.assertEqual(self.builds[1].name, 'project-test2')
3172
3173 self.worker.release('project-.*')
3174 self.waitUntilSettled()
3175
3176 # C successfully merged so window is bumped to 3.
3177 self.assertEqual(queue.window, 3)
3178 self.assertEqual(queue.window_floor, 1)
3179 self.assertEqual(C.data['status'], 'MERGED')
3180
3181 def test_queue_rate_limiting_dependent(self):
3182 "Test that DependentPipelines are rate limited with dep in window"
James E. Blairf84026c2015-12-08 16:11:46 -08003183 self.updateConfigLayout(
3184 'tests/fixtures/layout-rate-limit.yaml')
Clark Boylan7603a372014-01-21 11:43:20 -08003185 self.sched.reconfigure(self.config)
3186 self.worker.hold_jobs_in_build = True
3187 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3188 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
3189 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
3190
3191 B.setDependsOn(A, 1)
3192
3193 self.worker.addFailTest('project-test1', A)
3194
3195 A.addApproval('CRVW', 2)
3196 B.addApproval('CRVW', 2)
3197 C.addApproval('CRVW', 2)
3198
3199 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3200 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3201 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
3202 self.waitUntilSettled()
3203
3204 # Only A and B will have their merge jobs queued because
3205 # window is 2.
3206 self.assertEqual(len(self.builds), 2)
3207 self.assertEqual(self.builds[0].name, 'project-merge')
3208 self.assertEqual(self.builds[1].name, 'project-merge')
3209
3210 self.worker.release('.*-merge')
3211 self.waitUntilSettled()
3212 self.worker.release('.*-merge')
3213 self.waitUntilSettled()
3214
3215 # Only A and B will have their test jobs queued because
3216 # window is 2.
3217 self.assertEqual(len(self.builds), 4)
3218 self.assertEqual(self.builds[0].name, 'project-test1')
3219 self.assertEqual(self.builds[1].name, 'project-test2')
3220 self.assertEqual(self.builds[2].name, 'project-test1')
3221 self.assertEqual(self.builds[3].name, 'project-test2')
3222
3223 self.worker.release('project-.*')
3224 self.waitUntilSettled()
3225
3226 queue = self.sched.layout.pipelines['gate'].queues[0]
3227 # A failed so window is reduced by 1 to 1.
3228 self.assertEqual(queue.window, 1)
3229 self.assertEqual(queue.window_floor, 1)
3230 self.assertEqual(A.data['status'], 'NEW')
3231 self.assertEqual(B.data['status'], 'NEW')
3232
3233 # Gate is reset and only C's merge job is queued because
3234 # window shrunk to 1 and A and B were dequeued.
3235 self.assertEqual(len(self.builds), 1)
3236 self.assertEqual(self.builds[0].name, 'project-merge')
3237
3238 self.worker.release('.*-merge')
3239 self.waitUntilSettled()
3240
3241 # Only C's test jobs are queued because window is still 1.
3242 self.assertEqual(len(self.builds), 2)
3243 self.assertEqual(self.builds[0].name, 'project-test1')
3244 self.assertEqual(self.builds[1].name, 'project-test2')
3245
3246 self.worker.release('project-.*')
3247 self.waitUntilSettled()
3248
3249 # C was successfully merged so window is increased to 2.
3250 self.assertEqual(queue.window, 2)
3251 self.assertEqual(queue.window_floor, 1)
3252 self.assertEqual(C.data['status'], 'MERGED')
Joshua Heskethba8776a2014-01-12 14:35:40 +08003253
3254 def test_worker_update_metadata(self):
3255 "Test if a worker can send back metadata about itself"
3256 self.worker.hold_jobs_in_build = True
3257
3258 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3259 A.addApproval('CRVW', 2)
3260 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3261 self.waitUntilSettled()
3262
3263 self.assertEqual(len(self.launcher.builds), 1)
3264
3265 self.log.debug('Current builds:')
3266 self.log.debug(self.launcher.builds)
3267
3268 start = time.time()
3269 while True:
3270 if time.time() - start > 10:
3271 raise Exception("Timeout waiting for gearman server to report "
3272 + "back to the client")
3273 build = self.launcher.builds.values()[0]
3274 if build.worker.name == "My Worker":
3275 break
3276 else:
3277 time.sleep(0)
3278
3279 self.log.debug(build)
3280 self.assertEqual("My Worker", build.worker.name)
3281 self.assertEqual("localhost", build.worker.hostname)
3282 self.assertEqual(['127.0.0.1', '192.168.1.1'], build.worker.ips)
3283 self.assertEqual("zuul.example.org", build.worker.fqdn)
3284 self.assertEqual("FakeBuilder", build.worker.program)
3285 self.assertEqual("v1.1", build.worker.version)
3286 self.assertEqual({'something': 'else'}, build.worker.extra)
3287
3288 self.worker.hold_jobs_in_build = False
3289 self.worker.release()
3290 self.waitUntilSettled()
Joshua Hesketh3979e3e2014-03-04 11:21:10 +11003291
3292 def test_footer_message(self):
3293 "Test a pipeline's footer message is correctly added to the report."
James E. Blairf84026c2015-12-08 16:11:46 -08003294 self.updateConfigLayout(
3295 'tests/fixtures/layout-footer-message.yaml')
Joshua Hesketh3979e3e2014-03-04 11:21:10 +11003296 self.sched.reconfigure(self.config)
3297 self.registerJobs()
3298
3299 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3300 A.addApproval('CRVW', 2)
3301 self.worker.addFailTest('test1', A)
3302 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3303 self.waitUntilSettled()
3304
3305 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
3306 B.addApproval('CRVW', 2)
3307 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3308 self.waitUntilSettled()
3309
3310 self.assertEqual(2, len(self.smtp_messages))
3311
3312 failure_body = """\
3313Build failed. For information on how to proceed, see \
3314http://wiki.example.org/Test_Failures
3315
3316- test1 http://logs.example.com/1/1/gate/test1/0 : FAILURE in 0s
3317- test2 http://logs.example.com/1/1/gate/test2/1 : SUCCESS in 0s
3318
3319For CI problems and help debugging, contact ci@example.org"""
3320
3321 success_body = """\
3322Build succeeded.
3323
3324- test1 http://logs.example.com/2/1/gate/test1/2 : SUCCESS in 0s
3325- test2 http://logs.example.com/2/1/gate/test2/3 : SUCCESS in 0s
3326
3327For CI problems and help debugging, contact ci@example.org"""
3328
3329 self.assertEqual(failure_body, self.smtp_messages[0]['body'])
3330 self.assertEqual(success_body, self.smtp_messages[1]['body'])
Joshua Heskethb7179772014-01-30 23:30:46 +11003331
3332 def test_merge_failure_reporters(self):
3333 """Check that the config is set up correctly"""
3334
James E. Blairf84026c2015-12-08 16:11:46 -08003335 self.updateConfigLayout(
3336 'tests/fixtures/layout-merge-failure.yaml')
Joshua Heskethb7179772014-01-30 23:30:46 +11003337 self.sched.reconfigure(self.config)
3338 self.registerJobs()
3339
3340 self.assertEqual(
Jeremy Stanley1c2c3c22015-06-15 21:23:19 +00003341 "Merge Failed.\n\nThis change or one of its cross-repo "
3342 "dependencies was unable to be automatically merged with the "
3343 "current state of its repository. Please rebase the change and "
3344 "upload a new patchset.",
Joshua Heskethb7179772014-01-30 23:30:46 +11003345 self.sched.layout.pipelines['check'].merge_failure_message)
3346 self.assertEqual(
3347 "The merge failed! For more information...",
3348 self.sched.layout.pipelines['gate'].merge_failure_message)
3349
3350 self.assertEqual(
3351 len(self.sched.layout.pipelines['check'].merge_failure_actions), 1)
3352 self.assertEqual(
3353 len(self.sched.layout.pipelines['gate'].merge_failure_actions), 2)
3354
3355 self.assertTrue(isinstance(
Joshua Heskethde958652015-11-10 19:19:50 +11003356 self.sched.layout.pipelines['check'].merge_failure_actions[0],
3357 zuul.reporter.gerrit.GerritReporter))
Joshua Heskethb7179772014-01-30 23:30:46 +11003358
3359 self.assertTrue(
3360 (
3361 isinstance(self.sched.layout.pipelines['gate'].
Joshua Heskethde958652015-11-10 19:19:50 +11003362 merge_failure_actions[0],
Joshua Heskethffe42062014-09-05 21:43:52 +10003363 zuul.reporter.smtp.SMTPReporter) and
Joshua Heskethb7179772014-01-30 23:30:46 +11003364 isinstance(self.sched.layout.pipelines['gate'].
Joshua Heskethde958652015-11-10 19:19:50 +11003365 merge_failure_actions[1],
Joshua Heskethffe42062014-09-05 21:43:52 +10003366 zuul.reporter.gerrit.GerritReporter)
Joshua Heskethb7179772014-01-30 23:30:46 +11003367 ) or (
3368 isinstance(self.sched.layout.pipelines['gate'].
Joshua Heskethde958652015-11-10 19:19:50 +11003369 merge_failure_actions[0],
Joshua Heskethffe42062014-09-05 21:43:52 +10003370 zuul.reporter.gerrit.GerritReporter) and
Joshua Heskethb7179772014-01-30 23:30:46 +11003371 isinstance(self.sched.layout.pipelines['gate'].
Joshua Heskethde958652015-11-10 19:19:50 +11003372 merge_failure_actions[1],
Joshua Heskethffe42062014-09-05 21:43:52 +10003373 zuul.reporter.smtp.SMTPReporter)
Joshua Heskethb7179772014-01-30 23:30:46 +11003374 )
3375 )
3376
3377 def test_merge_failure_reports(self):
3378 """Check that when a change fails to merge the correct message is sent
3379 to the correct reporter"""
James E. Blairf84026c2015-12-08 16:11:46 -08003380 self.updateConfigLayout(
3381 'tests/fixtures/layout-merge-failure.yaml')
Joshua Heskethb7179772014-01-30 23:30:46 +11003382 self.sched.reconfigure(self.config)
3383 self.registerJobs()
3384
3385 # Check a test failure isn't reported to SMTP
3386 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3387 A.addApproval('CRVW', 2)
3388 self.worker.addFailTest('project-test1', A)
3389 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3390 self.waitUntilSettled()
3391
3392 self.assertEqual(3, len(self.history)) # 3 jobs
3393 self.assertEqual(0, len(self.smtp_messages))
3394
3395 # Check a merge failure is reported to SMTP
3396 # B should be merged, but C will conflict with B
3397 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
3398 B.addPatchset(['conflict'])
3399 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
3400 C.addPatchset(['conflict'])
3401 B.addApproval('CRVW', 2)
3402 C.addApproval('CRVW', 2)
3403 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3404 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
3405 self.waitUntilSettled()
3406
3407 self.assertEqual(6, len(self.history)) # A and B jobs
3408 self.assertEqual(1, len(self.smtp_messages))
3409 self.assertEqual('The merge failed! For more information...',
3410 self.smtp_messages[0]['body'])
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11003411
3412 def test_swift_instructions(self):
3413 "Test that the correct swift instructions are sent to the workers"
James E. Blairf84026c2015-12-08 16:11:46 -08003414 self.updateConfigLayout(
3415 'tests/fixtures/layout-swift.yaml')
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11003416 self.sched.reconfigure(self.config)
3417 self.registerJobs()
3418
3419 self.worker.hold_jobs_in_build = True
3420 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3421
3422 A.addApproval('CRVW', 2)
3423 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3424 self.waitUntilSettled()
3425
3426 self.assertEqual(
3427 "https://storage.example.org/V1/AUTH_account/merge_logs/1/1/1/"
3428 "gate/test-merge/",
Joshua Hesketh76dee532014-07-03 15:39:13 +10003429 self.builds[0].parameters['SWIFT_logs_URL'][:-7])
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11003430 self.assertEqual(5,
3431 len(self.builds[0].parameters['SWIFT_logs_HMAC_BODY'].
3432 split('\n')))
3433 self.assertIn('SWIFT_logs_SIGNATURE', self.builds[0].parameters)
3434
3435 self.assertEqual(
3436 "https://storage.example.org/V1/AUTH_account/logs/1/1/1/"
3437 "gate/test-test/",
Joshua Hesketh76dee532014-07-03 15:39:13 +10003438 self.builds[1].parameters['SWIFT_logs_URL'][:-7])
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11003439 self.assertEqual(5,
3440 len(self.builds[1].parameters['SWIFT_logs_HMAC_BODY'].
3441 split('\n')))
3442 self.assertIn('SWIFT_logs_SIGNATURE', self.builds[1].parameters)
3443
3444 self.assertEqual(
3445 "https://storage.example.org/V1/AUTH_account/stash/1/1/1/"
3446 "gate/test-test/",
Joshua Hesketh76dee532014-07-03 15:39:13 +10003447 self.builds[1].parameters['SWIFT_MOSTLY_URL'][:-7])
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11003448 self.assertEqual(5,
3449 len(self.builds[1].
3450 parameters['SWIFT_MOSTLY_HMAC_BODY'].split('\n')))
3451 self.assertIn('SWIFT_MOSTLY_SIGNATURE', self.builds[1].parameters)
3452
3453 self.worker.hold_jobs_in_build = False
3454 self.worker.release()
3455 self.waitUntilSettled()
Joshua Hesketh85af4e92014-02-21 08:28:58 -08003456
3457 def test_client_get_running_jobs(self):
3458 "Test that the RPC client can get a list of running jobs"
3459 self.worker.hold_jobs_in_build = True
3460 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3461 A.addApproval('CRVW', 2)
3462 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3463 self.waitUntilSettled()
3464
3465 client = zuul.rpcclient.RPCClient('127.0.0.1',
3466 self.gearman_server.port)
3467
3468 # Wait for gearman server to send the initial workData back to zuul
3469 start = time.time()
3470 while True:
3471 if time.time() - start > 10:
3472 raise Exception("Timeout waiting for gearman server to report "
3473 + "back to the client")
3474 build = self.launcher.builds.values()[0]
3475 if build.worker.name == "My Worker":
3476 break
3477 else:
3478 time.sleep(0)
3479
3480 running_items = client.get_running_jobs()
3481
3482 self.assertEqual(1, len(running_items))
3483 running_item = running_items[0]
3484 self.assertEqual([], running_item['failing_reasons'])
3485 self.assertEqual([], running_item['items_behind'])
3486 self.assertEqual('https://hostname/1', running_item['url'])
3487 self.assertEqual(None, running_item['item_ahead'])
3488 self.assertEqual('org/project', running_item['project'])
3489 self.assertEqual(None, running_item['remaining_time'])
3490 self.assertEqual(True, running_item['active'])
3491 self.assertEqual('1,1', running_item['id'])
3492
3493 self.assertEqual(3, len(running_item['jobs']))
3494 for job in running_item['jobs']:
3495 if job['name'] == 'project-merge':
3496 self.assertEqual('project-merge', job['name'])
3497 self.assertEqual('gate', job['pipeline'])
3498 self.assertEqual(False, job['retry'])
Joshua Hesketh85af4e92014-02-21 08:28:58 -08003499 self.assertEqual('https://server/job/project-merge/0/',
3500 job['url'])
3501 self.assertEqual(7, len(job['worker']))
3502 self.assertEqual(False, job['canceled'])
3503 self.assertEqual(True, job['voting'])
3504 self.assertEqual(None, job['result'])
3505 self.assertEqual('gate', job['pipeline'])
3506 break
3507
3508 self.worker.hold_jobs_in_build = False
3509 self.worker.release()
3510 self.waitUntilSettled()
3511
3512 running_items = client.get_running_jobs()
3513 self.assertEqual(0, len(running_items))
James E. Blairbadc1ad2014-04-28 13:55:14 -07003514
3515 def test_nonvoting_pipeline(self):
3516 "Test that a nonvoting pipeline (experimental) can still report"
3517
Joshua Heskethcc017ea2014-04-30 19:55:25 +10003518 A = self.fake_gerrit.addFakeChange('org/experimental-project',
3519 'master', 'A')
James E. Blairbadc1ad2014-04-28 13:55:14 -07003520 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3521 self.waitUntilSettled()
Joshua Heskethcc017ea2014-04-30 19:55:25 +10003522 self.assertEqual(
3523 self.getJobFromHistory('experimental-project-test').result,
3524 'SUCCESS')
James E. Blairbadc1ad2014-04-28 13:55:14 -07003525 self.assertEqual(A.reported, 1)
James E. Blair5ee24252014-12-30 10:12:29 -08003526
3527 def test_crd_gate(self):
3528 "Test cross-repo dependencies"
3529 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3530 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3531 A.addApproval('CRVW', 2)
3532 B.addApproval('CRVW', 2)
3533
3534 AM2 = self.fake_gerrit.addFakeChange('org/project1', 'master', 'AM2')
3535 AM1 = self.fake_gerrit.addFakeChange('org/project1', 'master', 'AM1')
3536 AM2.setMerged()
3537 AM1.setMerged()
3538
3539 BM2 = self.fake_gerrit.addFakeChange('org/project2', 'master', 'BM2')
3540 BM1 = self.fake_gerrit.addFakeChange('org/project2', 'master', 'BM1')
3541 BM2.setMerged()
3542 BM1.setMerged()
3543
3544 # A -> AM1 -> AM2
3545 # B -> BM1 -> BM2
3546 # A Depends-On: B
3547 # M2 is here to make sure it is never queried. If it is, it
3548 # means zuul is walking down the entire history of merged
3549 # changes.
3550
3551 B.setDependsOn(BM1, 1)
3552 BM1.setDependsOn(BM2, 1)
3553
3554 A.setDependsOn(AM1, 1)
3555 AM1.setDependsOn(AM2, 1)
3556
3557 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3558 A.subject, B.data['id'])
3559
3560 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3561 self.waitUntilSettled()
3562
3563 self.assertEqual(A.data['status'], 'NEW')
3564 self.assertEqual(B.data['status'], 'NEW')
3565
3566 source = self.sched.layout.pipelines['gate'].source
3567 source.maintainCache([])
3568
3569 self.worker.hold_jobs_in_build = True
3570 B.addApproval('APRV', 1)
3571 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3572 self.waitUntilSettled()
3573
3574 self.worker.release('.*-merge')
3575 self.waitUntilSettled()
3576 self.worker.release('.*-merge')
3577 self.waitUntilSettled()
3578 self.worker.hold_jobs_in_build = False
3579 self.worker.release()
3580 self.waitUntilSettled()
3581
3582 self.assertEqual(AM2.queried, 0)
3583 self.assertEqual(BM2.queried, 0)
3584 self.assertEqual(A.data['status'], 'MERGED')
3585 self.assertEqual(B.data['status'], 'MERGED')
3586 self.assertEqual(A.reported, 2)
3587 self.assertEqual(B.reported, 2)
3588
James E. Blair8f78d882015-02-05 08:51:37 -08003589 self.assertEqual(self.getJobFromHistory('project1-merge').changes,
3590 '2,1 1,1')
3591
3592 def test_crd_branch(self):
3593 "Test cross-repo dependencies in multiple branches"
3594 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3595 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3596 C = self.fake_gerrit.addFakeChange('org/project2', 'mp', 'C')
3597 C.data['id'] = B.data['id']
3598 A.addApproval('CRVW', 2)
3599 B.addApproval('CRVW', 2)
3600 C.addApproval('CRVW', 2)
3601
3602 # A Depends-On: B+C
3603 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3604 A.subject, B.data['id'])
3605
3606 self.worker.hold_jobs_in_build = True
3607 B.addApproval('APRV', 1)
3608 C.addApproval('APRV', 1)
3609 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3610 self.waitUntilSettled()
3611
3612 self.worker.release('.*-merge')
3613 self.waitUntilSettled()
3614 self.worker.release('.*-merge')
3615 self.waitUntilSettled()
3616 self.worker.release('.*-merge')
3617 self.waitUntilSettled()
3618 self.worker.hold_jobs_in_build = False
3619 self.worker.release()
3620 self.waitUntilSettled()
3621
3622 self.assertEqual(A.data['status'], 'MERGED')
3623 self.assertEqual(B.data['status'], 'MERGED')
3624 self.assertEqual(C.data['status'], 'MERGED')
3625 self.assertEqual(A.reported, 2)
3626 self.assertEqual(B.reported, 2)
3627 self.assertEqual(C.reported, 2)
3628
3629 self.assertEqual(self.getJobFromHistory('project1-merge').changes,
3630 '2,1 3,1 1,1')
3631
3632 def test_crd_multiline(self):
3633 "Test multiple depends-on lines in commit"
3634 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3635 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3636 C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
3637 A.addApproval('CRVW', 2)
3638 B.addApproval('CRVW', 2)
3639 C.addApproval('CRVW', 2)
3640
3641 # A Depends-On: B+C
3642 A.data['commitMessage'] = '%s\n\nDepends-On: %s\nDepends-On: %s\n' % (
3643 A.subject, B.data['id'], C.data['id'])
3644
3645 self.worker.hold_jobs_in_build = True
3646 B.addApproval('APRV', 1)
3647 C.addApproval('APRV', 1)
3648 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3649 self.waitUntilSettled()
3650
3651 self.worker.release('.*-merge')
3652 self.waitUntilSettled()
3653 self.worker.release('.*-merge')
3654 self.waitUntilSettled()
3655 self.worker.release('.*-merge')
3656 self.waitUntilSettled()
3657 self.worker.hold_jobs_in_build = False
3658 self.worker.release()
3659 self.waitUntilSettled()
3660
3661 self.assertEqual(A.data['status'], 'MERGED')
3662 self.assertEqual(B.data['status'], 'MERGED')
3663 self.assertEqual(C.data['status'], 'MERGED')
3664 self.assertEqual(A.reported, 2)
3665 self.assertEqual(B.reported, 2)
3666 self.assertEqual(C.reported, 2)
3667
3668 self.assertEqual(self.getJobFromHistory('project1-merge').changes,
3669 '2,1 3,1 1,1')
James E. Blair5ee24252014-12-30 10:12:29 -08003670
3671 def test_crd_unshared_gate(self):
3672 "Test cross-repo dependencies in unshared gate queues"
3673 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3674 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
3675 A.addApproval('CRVW', 2)
3676 B.addApproval('CRVW', 2)
3677
3678 # A Depends-On: B
3679 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3680 A.subject, B.data['id'])
3681
3682 # A and B do not share a queue, make sure that A is unable to
3683 # enqueue B (and therefore, A is unable to be enqueued).
3684 B.addApproval('APRV', 1)
3685 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3686 self.waitUntilSettled()
3687
3688 self.assertEqual(A.data['status'], 'NEW')
3689 self.assertEqual(B.data['status'], 'NEW')
3690 self.assertEqual(A.reported, 0)
3691 self.assertEqual(B.reported, 0)
3692 self.assertEqual(len(self.history), 0)
3693
3694 # Enqueue and merge B alone.
3695 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3696 self.waitUntilSettled()
3697
3698 self.assertEqual(B.data['status'], 'MERGED')
3699 self.assertEqual(B.reported, 2)
3700
3701 # Now that B is merged, A should be able to be enqueued and
3702 # merged.
3703 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3704 self.waitUntilSettled()
3705
3706 self.assertEqual(A.data['status'], 'MERGED')
3707 self.assertEqual(A.reported, 2)
3708
James E. Blair96698e22015-04-02 07:48:21 -07003709 def test_crd_gate_reverse(self):
3710 "Test reverse cross-repo dependencies"
3711 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3712 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3713 A.addApproval('CRVW', 2)
3714 B.addApproval('CRVW', 2)
3715
3716 # A Depends-On: B
3717
3718 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3719 A.subject, B.data['id'])
3720
3721 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3722 self.waitUntilSettled()
3723
3724 self.assertEqual(A.data['status'], 'NEW')
3725 self.assertEqual(B.data['status'], 'NEW')
3726
3727 self.worker.hold_jobs_in_build = True
3728 A.addApproval('APRV', 1)
3729 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3730 self.waitUntilSettled()
3731
3732 self.worker.release('.*-merge')
3733 self.waitUntilSettled()
3734 self.worker.release('.*-merge')
3735 self.waitUntilSettled()
3736 self.worker.hold_jobs_in_build = False
3737 self.worker.release()
3738 self.waitUntilSettled()
3739
3740 self.assertEqual(A.data['status'], 'MERGED')
3741 self.assertEqual(B.data['status'], 'MERGED')
3742 self.assertEqual(A.reported, 2)
3743 self.assertEqual(B.reported, 2)
3744
3745 self.assertEqual(self.getJobFromHistory('project1-merge').changes,
3746 '2,1 1,1')
3747
James E. Blair5ee24252014-12-30 10:12:29 -08003748 def test_crd_cycle(self):
3749 "Test cross-repo dependency cycles"
3750 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3751 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3752 A.addApproval('CRVW', 2)
3753 B.addApproval('CRVW', 2)
3754
3755 # A -> B -> A (via commit-depends)
3756
3757 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3758 A.subject, B.data['id'])
3759 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3760 B.subject, A.data['id'])
3761
3762 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3763 self.waitUntilSettled()
3764
3765 self.assertEqual(A.reported, 0)
3766 self.assertEqual(B.reported, 0)
3767 self.assertEqual(A.data['status'], 'NEW')
3768 self.assertEqual(B.data['status'], 'NEW')
James E. Blairbfb8e042014-12-30 17:01:44 -08003769
Evgeny Antyshev0deaaad2015-08-03 20:22:56 +00003770 def test_crd_gate_unknown(self):
3771 "Test unknown projects in dependent pipeline"
3772 self.init_repo("org/unknown")
3773 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3774 B = self.fake_gerrit.addFakeChange('org/unknown', 'master', 'B')
3775 A.addApproval('CRVW', 2)
3776 B.addApproval('CRVW', 2)
3777
3778 # A Depends-On: B
3779 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3780 A.subject, B.data['id'])
3781
3782 B.addApproval('APRV', 1)
3783 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3784 self.waitUntilSettled()
3785
3786 # Unknown projects cannot share a queue with any other
3787 # since they don't have common jobs with any other (they have no jobs).
3788 # Changes which depend on unknown project changes
3789 # should not be processed in dependent pipeline
3790 self.assertEqual(A.data['status'], 'NEW')
3791 self.assertEqual(B.data['status'], 'NEW')
3792 self.assertEqual(A.reported, 0)
3793 self.assertEqual(B.reported, 0)
3794 self.assertEqual(len(self.history), 0)
3795
3796 # Simulate change B being gated outside this layout
3797 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3798 B.setMerged()
3799 self.waitUntilSettled()
3800 self.assertEqual(len(self.history), 0)
3801
3802 # Now that B is merged, A should be able to be enqueued and
3803 # merged.
3804 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3805 self.waitUntilSettled()
3806
3807 self.assertEqual(A.data['status'], 'MERGED')
3808 self.assertEqual(A.reported, 2)
3809 self.assertEqual(B.data['status'], 'MERGED')
3810 self.assertEqual(B.reported, 0)
3811
James E. Blairbfb8e042014-12-30 17:01:44 -08003812 def test_crd_check(self):
3813 "Test cross-repo dependencies in independent pipelines"
3814
3815 self.gearman_server.hold_jobs_in_queue = True
3816 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3817 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3818
3819 # A Depends-On: B
3820 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3821 A.subject, B.data['id'])
3822
3823 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3824 self.waitUntilSettled()
3825
3826 queue = self.gearman_server.getQueue()
3827 ref = self.getParameter(queue[-1], 'ZUUL_REF')
3828 self.gearman_server.hold_jobs_in_queue = False
3829 self.gearman_server.release()
3830 self.waitUntilSettled()
3831
3832 path = os.path.join(self.git_root, "org/project1")
3833 repo = git.Repo(path)
3834 repo_messages = [c.message.strip() for c in repo.iter_commits(ref)]
3835 repo_messages.reverse()
3836 correct_messages = ['initial commit', 'A-1']
3837 self.assertEqual(repo_messages, correct_messages)
3838
3839 path = os.path.join(self.git_root, "org/project2")
3840 repo = git.Repo(path)
3841 repo_messages = [c.message.strip() for c in repo.iter_commits(ref)]
3842 repo_messages.reverse()
3843 correct_messages = ['initial commit', 'B-1']
3844 self.assertEqual(repo_messages, correct_messages)
3845
3846 self.assertEqual(A.data['status'], 'NEW')
3847 self.assertEqual(B.data['status'], 'NEW')
3848 self.assertEqual(A.reported, 1)
3849 self.assertEqual(B.reported, 0)
3850
3851 self.assertEqual(self.history[0].changes, '2,1 1,1')
3852 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 0)
James E. Blair8f78d882015-02-05 08:51:37 -08003853
James E. Blairdbfe1cd2015-02-07 11:41:19 -08003854 def test_crd_check_git_depends(self):
3855 "Test single-repo dependencies in independent pipelines"
James E. Blairb8c16472015-05-05 14:55:26 -07003856 self.gearman_server.hold_jobs_in_build = True
James E. Blairdbfe1cd2015-02-07 11:41:19 -08003857 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3858 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
3859
3860 # Add two git-dependent changes and make sure they both report
3861 # success.
3862 B.setDependsOn(A, 1)
3863 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3864 self.waitUntilSettled()
3865 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
3866 self.waitUntilSettled()
3867
James E. Blairb8c16472015-05-05 14:55:26 -07003868 self.orderedRelease()
3869 self.gearman_server.hold_jobs_in_build = False
James E. Blairdbfe1cd2015-02-07 11:41:19 -08003870 self.waitUntilSettled()
3871
3872 self.assertEqual(A.data['status'], 'NEW')
3873 self.assertEqual(B.data['status'], 'NEW')
3874 self.assertEqual(A.reported, 1)
3875 self.assertEqual(B.reported, 1)
3876
3877 self.assertEqual(self.history[0].changes, '1,1')
3878 self.assertEqual(self.history[-1].changes, '1,1 2,1')
3879 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 0)
3880
3881 self.assertIn('Build succeeded', A.messages[0])
3882 self.assertIn('Build succeeded', B.messages[0])
3883
3884 def test_crd_check_duplicate(self):
3885 "Test duplicate check in independent pipelines"
James E. Blair1e263032015-05-07 14:35:34 -07003886 self.worker.hold_jobs_in_build = True
James E. Blairdbfe1cd2015-02-07 11:41:19 -08003887 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3888 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
3889 check_pipeline = self.sched.layout.pipelines['check']
3890
3891 # Add two git-dependent changes...
3892 B.setDependsOn(A, 1)
3893 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
3894 self.waitUntilSettled()
3895 self.assertEqual(len(check_pipeline.getAllItems()), 2)
3896
3897 # ...make sure the live one is not duplicated...
3898 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
3899 self.waitUntilSettled()
3900 self.assertEqual(len(check_pipeline.getAllItems()), 2)
3901
3902 # ...but the non-live one is able to be.
3903 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3904 self.waitUntilSettled()
3905 self.assertEqual(len(check_pipeline.getAllItems()), 3)
3906
Clark Boylandd849822015-03-02 12:38:14 -08003907 # Release jobs in order to avoid races with change A jobs
3908 # finishing before change B jobs.
James E. Blaird7650852015-05-07 15:47:37 -07003909 self.orderedRelease()
James E. Blair1e263032015-05-07 14:35:34 -07003910 self.worker.hold_jobs_in_build = False
3911 self.worker.release()
James E. Blairdbfe1cd2015-02-07 11:41:19 -08003912 self.waitUntilSettled()
3913
3914 self.assertEqual(A.data['status'], 'NEW')
3915 self.assertEqual(B.data['status'], 'NEW')
3916 self.assertEqual(A.reported, 1)
3917 self.assertEqual(B.reported, 1)
3918
3919 self.assertEqual(self.history[0].changes, '1,1 2,1')
3920 self.assertEqual(self.history[1].changes, '1,1')
3921 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 0)
3922
3923 self.assertIn('Build succeeded', A.messages[0])
3924 self.assertIn('Build succeeded', B.messages[0])
3925
Evgeny Antyshev0deaaad2015-08-03 20:22:56 +00003926 def _test_crd_check_reconfiguration(self, project1, project2):
James E. Blair8f78d882015-02-05 08:51:37 -08003927 "Test cross-repo dependencies re-enqueued in independent pipelines"
3928
3929 self.gearman_server.hold_jobs_in_queue = True
Evgeny Antyshev0deaaad2015-08-03 20:22:56 +00003930 A = self.fake_gerrit.addFakeChange(project1, 'master', 'A')
3931 B = self.fake_gerrit.addFakeChange(project2, 'master', 'B')
James E. Blair8f78d882015-02-05 08:51:37 -08003932
3933 # A Depends-On: B
3934 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3935 A.subject, B.data['id'])
3936
3937 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3938 self.waitUntilSettled()
3939
3940 self.sched.reconfigure(self.config)
3941
3942 # Make sure the items still share a change queue, and the
3943 # first one is not live.
3944 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 1)
3945 queue = self.sched.layout.pipelines['check'].queues[0]
3946 first_item = queue.queue[0]
3947 for item in queue.queue:
3948 self.assertEqual(item.queue, first_item.queue)
3949 self.assertFalse(first_item.live)
3950 self.assertTrue(queue.queue[1].live)
3951
3952 self.gearman_server.hold_jobs_in_queue = False
3953 self.gearman_server.release()
3954 self.waitUntilSettled()
3955
3956 self.assertEqual(A.data['status'], 'NEW')
3957 self.assertEqual(B.data['status'], 'NEW')
3958 self.assertEqual(A.reported, 1)
3959 self.assertEqual(B.reported, 0)
3960
3961 self.assertEqual(self.history[0].changes, '2,1 1,1')
3962 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 0)
James E. Blair17dd6772015-02-09 14:45:18 -08003963
Evgeny Antyshev0deaaad2015-08-03 20:22:56 +00003964 def test_crd_check_reconfiguration(self):
3965 self._test_crd_check_reconfiguration('org/project1', 'org/project2')
3966
3967 def test_crd_undefined_project(self):
3968 """Test that undefined projects in dependencies are handled for
3969 independent pipelines"""
3970 # It's a hack for fake gerrit,
3971 # as it implies repo creation upon the creation of any change
3972 self.init_repo("org/unknown")
3973 self._test_crd_check_reconfiguration('org/project1', 'org/unknown')
3974
James E. Blair17dd6772015-02-09 14:45:18 -08003975 def test_crd_check_ignore_dependencies(self):
3976 "Test cross-repo dependencies can be ignored"
James E. Blairf84026c2015-12-08 16:11:46 -08003977 self.updateConfigLayout(
3978 'tests/fixtures/layout-ignore-dependencies.yaml')
James E. Blair17dd6772015-02-09 14:45:18 -08003979 self.sched.reconfigure(self.config)
3980 self.registerJobs()
3981
3982 self.gearman_server.hold_jobs_in_queue = True
3983 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3984 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3985 C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
3986
3987 # A Depends-On: B
3988 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3989 A.subject, B.data['id'])
3990 # C git-depends on B
3991 C.setDependsOn(B, 1)
3992 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3993 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
3994 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
3995 self.waitUntilSettled()
3996
3997 # Make sure none of the items share a change queue, and all
3998 # are live.
3999 check_pipeline = self.sched.layout.pipelines['check']
4000 self.assertEqual(len(check_pipeline.queues), 3)
4001 self.assertEqual(len(check_pipeline.getAllItems()), 3)
4002 for item in check_pipeline.getAllItems():
4003 self.assertTrue(item.live)
4004
4005 self.gearman_server.hold_jobs_in_queue = False
4006 self.gearman_server.release()
4007 self.waitUntilSettled()
4008
4009 self.assertEqual(A.data['status'], 'NEW')
4010 self.assertEqual(B.data['status'], 'NEW')
4011 self.assertEqual(C.data['status'], 'NEW')
4012 self.assertEqual(A.reported, 1)
4013 self.assertEqual(B.reported, 1)
4014 self.assertEqual(C.reported, 1)
4015
4016 # Each job should have tested exactly one change
4017 for job in self.history:
4018 self.assertEqual(len(job.changes.split()), 1)
James E. Blair96698e22015-04-02 07:48:21 -07004019
4020 def test_crd_check_transitive(self):
4021 "Test transitive cross-repo dependencies"
4022 # Specifically, if A -> B -> C, and C gets a new patchset and
4023 # A gets a new patchset, ensure the test of A,2 includes B,1
4024 # and C,2 (not C,1 which would indicate stale data in the
4025 # cache for B).
4026 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
4027 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
4028 C = self.fake_gerrit.addFakeChange('org/project3', 'master', 'C')
4029
4030 # A Depends-On: B
4031 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
4032 A.subject, B.data['id'])
4033
4034 # B Depends-On: C
4035 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
4036 B.subject, C.data['id'])
4037
4038 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
4039 self.waitUntilSettled()
4040 self.assertEqual(self.history[-1].changes, '3,1 2,1 1,1')
4041
4042 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
4043 self.waitUntilSettled()
4044 self.assertEqual(self.history[-1].changes, '3,1 2,1')
4045
4046 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
4047 self.waitUntilSettled()
4048 self.assertEqual(self.history[-1].changes, '3,1')
4049
4050 C.addPatchset()
4051 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(2))
4052 self.waitUntilSettled()
4053 self.assertEqual(self.history[-1].changes, '3,2')
4054
4055 A.addPatchset()
4056 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
4057 self.waitUntilSettled()
4058 self.assertEqual(self.history[-1].changes, '3,2 2,1 1,2')
Joshua Hesketh89e829d2015-02-10 16:29:45 +11004059
4060 def test_disable_at(self):
4061 "Test a pipeline will only report to the disabled trigger when failing"
4062
James E. Blairf84026c2015-12-08 16:11:46 -08004063 self.updateConfigLayout(
4064 'tests/fixtures/layout-disable-at.yaml')
Joshua Hesketh89e829d2015-02-10 16:29:45 +11004065 self.sched.reconfigure(self.config)
4066
4067 self.assertEqual(3, self.sched.layout.pipelines['check'].disable_at)
4068 self.assertEqual(
4069 0, self.sched.layout.pipelines['check']._consecutive_failures)
4070 self.assertFalse(self.sched.layout.pipelines['check']._disabled)
4071
4072 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
4073 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
4074 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
4075 D = self.fake_gerrit.addFakeChange('org/project', 'master', 'D')
4076 E = self.fake_gerrit.addFakeChange('org/project', 'master', 'E')
4077 F = self.fake_gerrit.addFakeChange('org/project', 'master', 'F')
4078 G = self.fake_gerrit.addFakeChange('org/project', 'master', 'G')
4079 H = self.fake_gerrit.addFakeChange('org/project', 'master', 'H')
4080 I = self.fake_gerrit.addFakeChange('org/project', 'master', 'I')
4081 J = self.fake_gerrit.addFakeChange('org/project', 'master', 'J')
4082 K = self.fake_gerrit.addFakeChange('org/project', 'master', 'K')
4083
4084 self.worker.addFailTest('project-test1', A)
4085 self.worker.addFailTest('project-test1', B)
4086 # Let C pass, resetting the counter
4087 self.worker.addFailTest('project-test1', D)
4088 self.worker.addFailTest('project-test1', E)
4089 self.worker.addFailTest('project-test1', F)
4090 self.worker.addFailTest('project-test1', G)
4091 self.worker.addFailTest('project-test1', H)
4092 # I also passes but should only report to the disabled reporters
4093 self.worker.addFailTest('project-test1', J)
4094 self.worker.addFailTest('project-test1', K)
4095
4096 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
4097 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
4098 self.waitUntilSettled()
4099
4100 self.assertEqual(
4101 2, self.sched.layout.pipelines['check']._consecutive_failures)
4102 self.assertFalse(self.sched.layout.pipelines['check']._disabled)
4103
4104 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
4105 self.waitUntilSettled()
4106
4107 self.assertEqual(
4108 0, self.sched.layout.pipelines['check']._consecutive_failures)
4109 self.assertFalse(self.sched.layout.pipelines['check']._disabled)
4110
4111 self.fake_gerrit.addEvent(D.getPatchsetCreatedEvent(1))
4112 self.fake_gerrit.addEvent(E.getPatchsetCreatedEvent(1))
4113 self.fake_gerrit.addEvent(F.getPatchsetCreatedEvent(1))
4114 self.waitUntilSettled()
4115
4116 # We should be disabled now
4117 self.assertEqual(
4118 3, self.sched.layout.pipelines['check']._consecutive_failures)
4119 self.assertTrue(self.sched.layout.pipelines['check']._disabled)
4120
4121 # We need to wait between each of these patches to make sure the
4122 # smtp messages come back in an expected order
4123 self.fake_gerrit.addEvent(G.getPatchsetCreatedEvent(1))
4124 self.waitUntilSettled()
4125 self.fake_gerrit.addEvent(H.getPatchsetCreatedEvent(1))
4126 self.waitUntilSettled()
4127 self.fake_gerrit.addEvent(I.getPatchsetCreatedEvent(1))
4128 self.waitUntilSettled()
4129
4130 # The first 6 (ABCDEF) jobs should have reported back to gerrt thus
4131 # leaving a message on each change
4132 self.assertEqual(1, len(A.messages))
4133 self.assertIn('Build failed.', A.messages[0])
4134 self.assertEqual(1, len(B.messages))
4135 self.assertIn('Build failed.', B.messages[0])
4136 self.assertEqual(1, len(C.messages))
4137 self.assertIn('Build succeeded.', C.messages[0])
4138 self.assertEqual(1, len(D.messages))
4139 self.assertIn('Build failed.', D.messages[0])
4140 self.assertEqual(1, len(E.messages))
4141 self.assertIn('Build failed.', E.messages[0])
4142 self.assertEqual(1, len(F.messages))
4143 self.assertIn('Build failed.', F.messages[0])
4144
4145 # The last 3 (GHI) would have only reported via smtp.
4146 self.assertEqual(3, len(self.smtp_messages))
4147 self.assertEqual(0, len(G.messages))
4148 self.assertIn('Build failed.', self.smtp_messages[0]['body'])
4149 self.assertIn('/7/1/check', self.smtp_messages[0]['body'])
4150 self.assertEqual(0, len(H.messages))
4151 self.assertIn('Build failed.', self.smtp_messages[1]['body'])
4152 self.assertIn('/8/1/check', self.smtp_messages[1]['body'])
4153 self.assertEqual(0, len(I.messages))
4154 self.assertIn('Build succeeded.', self.smtp_messages[2]['body'])
4155 self.assertIn('/9/1/check', self.smtp_messages[2]['body'])
4156
4157 # Now reload the configuration (simulate a HUP) to check the pipeline
4158 # comes out of disabled
4159 self.sched.reconfigure(self.config)
4160
4161 self.assertEqual(3, self.sched.layout.pipelines['check'].disable_at)
4162 self.assertEqual(
4163 0, self.sched.layout.pipelines['check']._consecutive_failures)
4164 self.assertFalse(self.sched.layout.pipelines['check']._disabled)
4165
4166 self.fake_gerrit.addEvent(J.getPatchsetCreatedEvent(1))
4167 self.fake_gerrit.addEvent(K.getPatchsetCreatedEvent(1))
4168 self.waitUntilSettled()
4169
4170 self.assertEqual(
4171 2, self.sched.layout.pipelines['check']._consecutive_failures)
4172 self.assertFalse(self.sched.layout.pipelines['check']._disabled)
4173
4174 # J and K went back to gerrit
4175 self.assertEqual(1, len(J.messages))
4176 self.assertIn('Build failed.', J.messages[0])
4177 self.assertEqual(1, len(K.messages))
4178 self.assertIn('Build failed.', K.messages[0])
4179 # No more messages reported via smtp
4180 self.assertEqual(3, len(self.smtp_messages))