blob: 7ed7efb280b0810b643fbaaceeba1983cd9c5156 [file] [log] [blame]
James E. Blairb0fcae42012-07-17 11:12:10 -07001#!/usr/bin/env python
2
3# Copyright 2012 Hewlett-Packard Development Company, L.P.
4#
5# Licensed under the Apache License, Version 2.0 (the "License"); you may
6# not use this file except in compliance with the License. You may obtain
7# a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations
15# under the License.
16
James E. Blairb0fcae42012-07-17 11:12:10 -070017import json
Monty Taylorbc758832013-06-17 17:22:42 -040018import logging
19import os
James E. Blairb0fcae42012-07-17 11:12:10 -070020import re
James E. Blair4886cc12012-07-18 15:39:41 -070021import shutil
Monty Taylorbc758832013-06-17 17:22:42 -040022import time
James E. Blair1843a552013-07-03 14:19:52 -070023import urllib
Monty Taylorbc758832013-06-17 17:22:42 -040024import urllib2
Maru Newby3fe5f852015-01-13 04:22:14 +000025import yaml
Monty Taylorbc758832013-06-17 17:22:42 -040026
James E. Blair4886cc12012-07-18 15:39:41 -070027import git
Monty Taylorbc758832013-06-17 17:22:42 -040028import testtools
James E. Blairb0fcae42012-07-17 11:12:10 -070029
Maru Newby3fe5f852015-01-13 04:22:14 +000030import zuul.change_matcher
James E. Blairb0fcae42012-07-17 11:12:10 -070031import zuul.scheduler
James E. Blairad28e912013-11-27 10:43:22 -080032import zuul.rpcclient
Joshua Hesketh1879cf72013-08-19 14:13:15 +100033import zuul.reporter.gerrit
Joshua Hesketh5fea8672013-08-19 17:32:01 +100034import zuul.reporter.smtp
James E. Blairb0fcae42012-07-17 11:12:10 -070035
Maru Newby3fe5f852015-01-13 04:22:14 +000036from tests.base import (
37 BaseTestCase,
38 ZuulTestCase,
39 repack_repo,
40)
James E. Blairb0fcae42012-07-17 11:12:10 -070041
James E. Blair1f4c2bb2013-04-26 08:40:46 -070042logging.basicConfig(level=logging.DEBUG,
43 format='%(asctime)s %(name)-32s '
44 '%(levelname)-8s %(message)s')
James E. Blairb0fcae42012-07-17 11:12:10 -070045
46
Maru Newby3fe5f852015-01-13 04:22:14 +000047class TestSchedulerConfigParsing(BaseTestCase):
48
49 def test_parse_skip_if(self):
50 job_yaml = """
51jobs:
52 - name: job_name
53 skip-if:
54 - project: ^project_name$
55 branch: ^stable/icehouse$
56 all-files-match-any:
57 - ^filename$
58 - project: ^project2_name$
59 all-files-match-any:
60 - ^filename2$
61 """.strip()
62 data = yaml.load(job_yaml)
63 config_job = data.get('jobs')[0]
64 sched = zuul.scheduler.Scheduler()
65 cm = zuul.change_matcher
66 expected = cm.MatchAny([
67 cm.MatchAll([
68 cm.ProjectMatcher('^project_name$'),
69 cm.BranchMatcher('^stable/icehouse$'),
70 cm.MatchAllFiles([cm.FileMatcher('^filename$')]),
71 ]),
72 cm.MatchAll([
73 cm.ProjectMatcher('^project2_name$'),
74 cm.MatchAllFiles([cm.FileMatcher('^filename2$')]),
75 ]),
76 ])
77 matcher = sched._parseSkipIf(config_job)
78 self.assertEqual(expected, matcher)
79
80
Clark Boylanb640e052014-04-03 16:41:46 -070081class TestScheduler(ZuulTestCase):
Antoine Mussobd86a312014-01-08 14:51:33 +010082
James E. Blairb0fcae42012-07-17 11:12:10 -070083 def test_jobs_launched(self):
84 "Test that jobs are launched and a change is merged"
James E. Blair1f4c2bb2013-04-26 08:40:46 -070085
James E. Blairb0fcae42012-07-17 11:12:10 -070086 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
James E. Blair8c803f82012-07-31 16:25:42 -070087 A.addApproval('CRVW', 2)
James E. Blairb0fcae42012-07-17 11:12:10 -070088 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
89 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -040090 self.assertEqual(self.getJobFromHistory('project-merge').result,
91 'SUCCESS')
92 self.assertEqual(self.getJobFromHistory('project-test1').result,
93 'SUCCESS')
94 self.assertEqual(self.getJobFromHistory('project-test2').result,
95 'SUCCESS')
96 self.assertEqual(A.data['status'], 'MERGED')
97 self.assertEqual(A.reported, 2)
James E. Blairb0fcae42012-07-17 11:12:10 -070098
James E. Blair66eeebf2013-07-27 17:44:32 -070099 self.assertReportedStat('gerrit.event.comment-added', value='1|c')
100 self.assertReportedStat('zuul.pipeline.gate.current_changes',
101 value='1|g')
102 self.assertReportedStat('zuul.pipeline.gate.job.project-merge.SUCCESS',
103 kind='ms')
104 self.assertReportedStat('zuul.pipeline.gate.job.project-merge.SUCCESS',
105 value='1|c')
106 self.assertReportedStat('zuul.pipeline.gate.resident_time', kind='ms')
107 self.assertReportedStat('zuul.pipeline.gate.total_changes',
108 value='1|c')
James E. Blair412e5582013-04-22 15:50:12 -0700109 self.assertReportedStat(
James E. Blair66eeebf2013-07-27 17:44:32 -0700110 'zuul.pipeline.gate.org.project.resident_time', kind='ms')
James E. Blair412e5582013-04-22 15:50:12 -0700111 self.assertReportedStat(
James E. Blair66eeebf2013-07-27 17:44:32 -0700112 'zuul.pipeline.gate.org.project.total_changes', value='1|c')
James E. Blair412e5582013-04-22 15:50:12 -0700113
James E. Blair3cb10702013-08-24 08:56:03 -0700114 def test_initial_pipeline_gauges(self):
115 "Test that each pipeline reported its length on start"
116 pipeline_names = self.sched.layout.pipelines.keys()
117 self.assertNotEqual(len(pipeline_names), 0)
118 for name in pipeline_names:
119 self.assertReportedStat('zuul.pipeline.%s.current_changes' % name,
120 value='0|g')
121
James E. Blair42f74822013-05-14 15:18:03 -0700122 def test_duplicate_pipelines(self):
123 "Test that a change matching multiple pipelines works"
James E. Blair1b4d9722013-05-21 10:32:04 -0700124
James E. Blair42f74822013-05-14 15:18:03 -0700125 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
126 self.fake_gerrit.addEvent(A.getChangeRestoredEvent())
127 self.waitUntilSettled()
James E. Blair42f74822013-05-14 15:18:03 -0700128
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400129 self.assertEqual(len(self.history), 2)
Monty Taylor6bef8ef2013-06-02 08:17:12 -0400130 self.history[0].name == 'project-test1'
131 self.history[1].name == 'project-test1'
James E. Blair42f74822013-05-14 15:18:03 -0700132
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400133 self.assertEqual(len(A.messages), 2)
James E. Blair42f74822013-05-14 15:18:03 -0700134 if 'dup1/project-test1' in A.messages[0]:
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400135 self.assertIn('dup1/project-test1', A.messages[0])
136 self.assertNotIn('dup2/project-test1', A.messages[0])
137 self.assertNotIn('dup1/project-test1', A.messages[1])
138 self.assertIn('dup2/project-test1', A.messages[1])
James E. Blair42f74822013-05-14 15:18:03 -0700139 else:
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400140 self.assertIn('dup1/project-test1', A.messages[1])
141 self.assertNotIn('dup2/project-test1', A.messages[1])
142 self.assertNotIn('dup1/project-test1', A.messages[0])
143 self.assertIn('dup2/project-test1', A.messages[0])
James E. Blair42f74822013-05-14 15:18:03 -0700144
James E. Blairb0fcae42012-07-17 11:12:10 -0700145 def test_parallel_changes(self):
146 "Test that changes are tested in parallel and merged in series"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700147
148 self.worker.hold_jobs_in_build = True
James E. Blairb0fcae42012-07-17 11:12:10 -0700149 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
150 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
151 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
James E. Blair8c803f82012-07-31 16:25:42 -0700152 A.addApproval('CRVW', 2)
153 B.addApproval('CRVW', 2)
154 C.addApproval('CRVW', 2)
James E. Blairb0fcae42012-07-17 11:12:10 -0700155
156 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
157 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
158 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
159
160 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400161 self.assertEqual(len(self.builds), 1)
162 self.assertEqual(self.builds[0].name, 'project-merge')
163 self.assertTrue(self.job_has_changes(self.builds[0], A))
James E. Blairb0fcae42012-07-17 11:12:10 -0700164
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700165 self.worker.release('.*-merge')
James E. Blairb0fcae42012-07-17 11:12:10 -0700166 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400167 self.assertEqual(len(self.builds), 3)
168 self.assertEqual(self.builds[0].name, 'project-test1')
169 self.assertTrue(self.job_has_changes(self.builds[0], A))
170 self.assertEqual(self.builds[1].name, 'project-test2')
171 self.assertTrue(self.job_has_changes(self.builds[1], A))
172 self.assertEqual(self.builds[2].name, 'project-merge')
173 self.assertTrue(self.job_has_changes(self.builds[2], A, B))
James E. Blairb0fcae42012-07-17 11:12:10 -0700174
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700175 self.worker.release('.*-merge')
James E. Blairb0fcae42012-07-17 11:12:10 -0700176 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400177 self.assertEqual(len(self.builds), 5)
178 self.assertEqual(self.builds[0].name, 'project-test1')
179 self.assertTrue(self.job_has_changes(self.builds[0], A))
180 self.assertEqual(self.builds[1].name, 'project-test2')
181 self.assertTrue(self.job_has_changes(self.builds[1], A))
James E. Blairb0fcae42012-07-17 11:12:10 -0700182
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400183 self.assertEqual(self.builds[2].name, 'project-test1')
184 self.assertTrue(self.job_has_changes(self.builds[2], A, B))
185 self.assertEqual(self.builds[3].name, 'project-test2')
186 self.assertTrue(self.job_has_changes(self.builds[3], A, B))
James E. Blairb0fcae42012-07-17 11:12:10 -0700187
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400188 self.assertEqual(self.builds[4].name, 'project-merge')
189 self.assertTrue(self.job_has_changes(self.builds[4], A, B, C))
James E. Blairb0fcae42012-07-17 11:12:10 -0700190
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700191 self.worker.release('.*-merge')
James E. Blairb0fcae42012-07-17 11:12:10 -0700192 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400193 self.assertEqual(len(self.builds), 6)
194 self.assertEqual(self.builds[0].name, 'project-test1')
195 self.assertTrue(self.job_has_changes(self.builds[0], A))
196 self.assertEqual(self.builds[1].name, 'project-test2')
197 self.assertTrue(self.job_has_changes(self.builds[1], A))
James E. Blairb0fcae42012-07-17 11:12:10 -0700198
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400199 self.assertEqual(self.builds[2].name, 'project-test1')
200 self.assertTrue(self.job_has_changes(self.builds[2], A, B))
201 self.assertEqual(self.builds[3].name, 'project-test2')
202 self.assertTrue(self.job_has_changes(self.builds[3], A, B))
James E. Blairb0fcae42012-07-17 11:12:10 -0700203
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400204 self.assertEqual(self.builds[4].name, 'project-test1')
205 self.assertTrue(self.job_has_changes(self.builds[4], A, B, C))
206 self.assertEqual(self.builds[5].name, 'project-test2')
207 self.assertTrue(self.job_has_changes(self.builds[5], A, B, C))
James E. Blairb0fcae42012-07-17 11:12:10 -0700208
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700209 self.worker.hold_jobs_in_build = False
210 self.worker.release()
James E. Blairb0fcae42012-07-17 11:12:10 -0700211 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400212 self.assertEqual(len(self.builds), 0)
James E. Blairb0fcae42012-07-17 11:12:10 -0700213
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400214 self.assertEqual(len(self.history), 9)
215 self.assertEqual(A.data['status'], 'MERGED')
216 self.assertEqual(B.data['status'], 'MERGED')
217 self.assertEqual(C.data['status'], 'MERGED')
218 self.assertEqual(A.reported, 2)
219 self.assertEqual(B.reported, 2)
220 self.assertEqual(C.reported, 2)
James E. Blairb02a3bb2012-07-30 17:49:55 -0700221
222 def test_failed_changes(self):
223 "Test that a change behind a failed change is retested"
James E. Blaire2819012013-06-28 17:17:26 -0400224 self.worker.hold_jobs_in_build = True
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700225
James E. Blairb02a3bb2012-07-30 17:49:55 -0700226 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
227 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
James E. Blair8c803f82012-07-31 16:25:42 -0700228 A.addApproval('CRVW', 2)
229 B.addApproval('CRVW', 2)
James E. Blairb02a3bb2012-07-30 17:49:55 -0700230
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700231 self.worker.addFailTest('project-test1', A)
James E. Blairb02a3bb2012-07-30 17:49:55 -0700232
James E. Blaire2819012013-06-28 17:17:26 -0400233 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
234 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
James E. Blairb02a3bb2012-07-30 17:49:55 -0700235 self.waitUntilSettled()
James E. Blaire2819012013-06-28 17:17:26 -0400236
237 self.worker.release('.*-merge')
238 self.waitUntilSettled()
239
240 self.worker.hold_jobs_in_build = False
241 self.worker.release()
242
243 self.waitUntilSettled()
244 # It's certain that the merge job for change 2 will run, but
245 # the test1 and test2 jobs may or may not run.
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400246 self.assertTrue(len(self.history) > 6)
247 self.assertEqual(A.data['status'], 'NEW')
248 self.assertEqual(B.data['status'], 'MERGED')
249 self.assertEqual(A.reported, 2)
250 self.assertEqual(B.reported, 2)
James E. Blairb02a3bb2012-07-30 17:49:55 -0700251
252 def test_independent_queues(self):
253 "Test that changes end up in the right queues"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700254
255 self.worker.hold_jobs_in_build = True
Zhongyue Luo5d556072012-09-21 02:00:47 +0900256 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
James E. Blairb02a3bb2012-07-30 17:49:55 -0700257 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
258 C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
James E. Blair8c803f82012-07-31 16:25:42 -0700259 A.addApproval('CRVW', 2)
260 B.addApproval('CRVW', 2)
261 C.addApproval('CRVW', 2)
James E. Blairb02a3bb2012-07-30 17:49:55 -0700262
263 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
264 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
265 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
266
James E. Blairb02a3bb2012-07-30 17:49:55 -0700267 self.waitUntilSettled()
268
269 # There should be one merge job at the head of each queue running
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400270 self.assertEqual(len(self.builds), 2)
271 self.assertEqual(self.builds[0].name, 'project-merge')
272 self.assertTrue(self.job_has_changes(self.builds[0], A))
273 self.assertEqual(self.builds[1].name, 'project1-merge')
274 self.assertTrue(self.job_has_changes(self.builds[1], B))
James E. Blairb02a3bb2012-07-30 17:49:55 -0700275
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700276 # Release the current merge builds
277 self.worker.release('.*-merge')
James E. Blairb02a3bb2012-07-30 17:49:55 -0700278 self.waitUntilSettled()
279 # Release the merge job for project2 which is behind project1
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700280 self.worker.release('.*-merge')
James E. Blairb02a3bb2012-07-30 17:49:55 -0700281 self.waitUntilSettled()
282
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700283 # All the test builds should be running:
James E. Blairb02a3bb2012-07-30 17:49:55 -0700284 # project1 (3) + project2 (3) + project (2) = 8
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400285 self.assertEqual(len(self.builds), 8)
James E. Blairb02a3bb2012-07-30 17:49:55 -0700286
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700287 self.worker.release()
James E. Blairb02a3bb2012-07-30 17:49:55 -0700288 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400289 self.assertEqual(len(self.builds), 0)
James E. Blairb02a3bb2012-07-30 17:49:55 -0700290
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400291 self.assertEqual(len(self.history), 11)
292 self.assertEqual(A.data['status'], 'MERGED')
293 self.assertEqual(B.data['status'], 'MERGED')
294 self.assertEqual(C.data['status'], 'MERGED')
295 self.assertEqual(A.reported, 2)
296 self.assertEqual(B.reported, 2)
297 self.assertEqual(C.reported, 2)
James E. Blaird466dc42012-07-31 10:42:56 -0700298
299 def test_failed_change_at_head(self):
300 "Test that if a change at the head fails, jobs behind it are canceled"
James E. Blaird466dc42012-07-31 10:42:56 -0700301
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700302 self.worker.hold_jobs_in_build = True
James E. Blaird466dc42012-07-31 10:42:56 -0700303 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
304 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
305 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
James E. Blair8c803f82012-07-31 16:25:42 -0700306 A.addApproval('CRVW', 2)
307 B.addApproval('CRVW', 2)
308 C.addApproval('CRVW', 2)
James E. Blaird466dc42012-07-31 10:42:56 -0700309
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700310 self.worker.addFailTest('project-test1', A)
James E. Blaird466dc42012-07-31 10:42:56 -0700311
312 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
313 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
314 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
315
316 self.waitUntilSettled()
James E. Blaird466dc42012-07-31 10:42:56 -0700317
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400318 self.assertEqual(len(self.builds), 1)
319 self.assertEqual(self.builds[0].name, 'project-merge')
320 self.assertTrue(self.job_has_changes(self.builds[0], A))
James E. Blaird466dc42012-07-31 10:42:56 -0700321
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700322 self.worker.release('.*-merge')
James E. Blaird466dc42012-07-31 10:42:56 -0700323 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700324 self.worker.release('.*-merge')
James E. Blaird466dc42012-07-31 10:42:56 -0700325 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700326 self.worker.release('.*-merge')
James E. Blaird466dc42012-07-31 10:42:56 -0700327 self.waitUntilSettled()
328
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400329 self.assertEqual(len(self.builds), 6)
330 self.assertEqual(self.builds[0].name, 'project-test1')
331 self.assertEqual(self.builds[1].name, 'project-test2')
332 self.assertEqual(self.builds[2].name, 'project-test1')
333 self.assertEqual(self.builds[3].name, 'project-test2')
334 self.assertEqual(self.builds[4].name, 'project-test1')
335 self.assertEqual(self.builds[5].name, 'project-test2')
James E. Blaird466dc42012-07-31 10:42:56 -0700336
Monty Taylor6bef8ef2013-06-02 08:17:12 -0400337 self.release(self.builds[0])
James E. Blaird466dc42012-07-31 10:42:56 -0700338 self.waitUntilSettled()
339
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400340 # project-test2, project-merge for B
341 self.assertEqual(len(self.builds), 2)
342 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 4)
James E. Blaird466dc42012-07-31 10:42:56 -0700343
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700344 self.worker.hold_jobs_in_build = False
345 self.worker.release()
James E. Blaird466dc42012-07-31 10:42:56 -0700346 self.waitUntilSettled()
347
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400348 self.assertEqual(len(self.builds), 0)
349 self.assertEqual(len(self.history), 15)
350 self.assertEqual(A.data['status'], 'NEW')
351 self.assertEqual(B.data['status'], 'MERGED')
352 self.assertEqual(C.data['status'], 'MERGED')
353 self.assertEqual(A.reported, 2)
354 self.assertEqual(B.reported, 2)
355 self.assertEqual(C.reported, 2)
James E. Blaird466dc42012-07-31 10:42:56 -0700356
James E. Blair0aac4872013-08-23 14:02:38 -0700357 def test_failed_change_in_middle(self):
358 "Test a failed change in the middle of the queue"
359
360 self.worker.hold_jobs_in_build = True
361 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
362 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
363 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
364 A.addApproval('CRVW', 2)
365 B.addApproval('CRVW', 2)
366 C.addApproval('CRVW', 2)
367
368 self.worker.addFailTest('project-test1', B)
369
370 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
371 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
372 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
373
374 self.waitUntilSettled()
375
376 self.worker.release('.*-merge')
377 self.waitUntilSettled()
378 self.worker.release('.*-merge')
379 self.waitUntilSettled()
380 self.worker.release('.*-merge')
381 self.waitUntilSettled()
382
383 self.assertEqual(len(self.builds), 6)
384 self.assertEqual(self.builds[0].name, 'project-test1')
385 self.assertEqual(self.builds[1].name, 'project-test2')
386 self.assertEqual(self.builds[2].name, 'project-test1')
387 self.assertEqual(self.builds[3].name, 'project-test2')
388 self.assertEqual(self.builds[4].name, 'project-test1')
389 self.assertEqual(self.builds[5].name, 'project-test2')
390
391 self.release(self.builds[2])
392 self.waitUntilSettled()
393
James E. Blair972e3c72013-08-29 12:04:55 -0700394 # project-test1 and project-test2 for A
395 # project-test2 for B
396 # project-merge for C (without B)
397 self.assertEqual(len(self.builds), 4)
James E. Blair0aac4872013-08-23 14:02:38 -0700398 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 2)
399
James E. Blair972e3c72013-08-29 12:04:55 -0700400 self.worker.release('.*-merge')
401 self.waitUntilSettled()
402
403 # project-test1 and project-test2 for A
404 # project-test2 for B
405 # project-test1 and project-test2 for C
406 self.assertEqual(len(self.builds), 5)
407
James E. Blair0aac4872013-08-23 14:02:38 -0700408 items = self.sched.layout.pipelines['gate'].getAllItems()
409 builds = items[0].current_build_set.getBuilds()
410 self.assertEqual(self.countJobResults(builds, 'SUCCESS'), 1)
411 self.assertEqual(self.countJobResults(builds, None), 2)
412 builds = items[1].current_build_set.getBuilds()
413 self.assertEqual(self.countJobResults(builds, 'SUCCESS'), 1)
414 self.assertEqual(self.countJobResults(builds, 'FAILURE'), 1)
415 self.assertEqual(self.countJobResults(builds, None), 1)
416 builds = items[2].current_build_set.getBuilds()
417 self.assertEqual(self.countJobResults(builds, 'SUCCESS'), 1)
James E. Blair972e3c72013-08-29 12:04:55 -0700418 self.assertEqual(self.countJobResults(builds, None), 2)
James E. Blair0aac4872013-08-23 14:02:38 -0700419
420 self.worker.hold_jobs_in_build = False
421 self.worker.release()
422 self.waitUntilSettled()
423
424 self.assertEqual(len(self.builds), 0)
425 self.assertEqual(len(self.history), 12)
426 self.assertEqual(A.data['status'], 'MERGED')
427 self.assertEqual(B.data['status'], 'NEW')
428 self.assertEqual(C.data['status'], 'MERGED')
429 self.assertEqual(A.reported, 2)
430 self.assertEqual(B.reported, 2)
431 self.assertEqual(C.reported, 2)
432
James E. Blaird466dc42012-07-31 10:42:56 -0700433 def test_failed_change_at_head_with_queue(self):
434 "Test that if a change at the head fails, queued jobs are canceled"
James E. Blaird466dc42012-07-31 10:42:56 -0700435
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700436 self.gearman_server.hold_jobs_in_queue = True
James E. Blaird466dc42012-07-31 10:42:56 -0700437 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
438 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
439 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
James E. Blair8c803f82012-07-31 16:25:42 -0700440 A.addApproval('CRVW', 2)
441 B.addApproval('CRVW', 2)
442 C.addApproval('CRVW', 2)
James E. Blaird466dc42012-07-31 10:42:56 -0700443
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700444 self.worker.addFailTest('project-test1', A)
James E. Blaird466dc42012-07-31 10:42:56 -0700445
446 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
447 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
448 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
449
450 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -0700451 queue = self.gearman_server.getQueue()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400452 self.assertEqual(len(self.builds), 0)
453 self.assertEqual(len(queue), 1)
454 self.assertEqual(queue[0].name, 'build:project-merge')
455 self.assertTrue(self.job_has_changes(queue[0], A))
James E. Blaird466dc42012-07-31 10:42:56 -0700456
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700457 self.gearman_server.release('.*-merge')
James E. Blaird466dc42012-07-31 10:42:56 -0700458 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700459 self.gearman_server.release('.*-merge')
James E. Blaird466dc42012-07-31 10:42:56 -0700460 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700461 self.gearman_server.release('.*-merge')
James E. Blaird466dc42012-07-31 10:42:56 -0700462 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -0700463 queue = self.gearman_server.getQueue()
James E. Blaird466dc42012-07-31 10:42:56 -0700464
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400465 self.assertEqual(len(self.builds), 0)
466 self.assertEqual(len(queue), 6)
467 self.assertEqual(queue[0].name, 'build:project-test1')
468 self.assertEqual(queue[1].name, 'build:project-test2')
469 self.assertEqual(queue[2].name, 'build:project-test1')
470 self.assertEqual(queue[3].name, 'build:project-test2')
471 self.assertEqual(queue[4].name, 'build:project-test1')
472 self.assertEqual(queue[5].name, 'build:project-test2')
James E. Blaird466dc42012-07-31 10:42:56 -0700473
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700474 self.release(queue[0])
James E. Blaird466dc42012-07-31 10:42:56 -0700475 self.waitUntilSettled()
476
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400477 self.assertEqual(len(self.builds), 0)
James E. Blair701c5b42013-06-06 09:34:59 -0700478 queue = self.gearman_server.getQueue()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400479 self.assertEqual(len(queue), 2) # project-test2, project-merge for B
480 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 0)
James E. Blaird466dc42012-07-31 10:42:56 -0700481
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700482 self.gearman_server.hold_jobs_in_queue = False
483 self.gearman_server.release()
James E. Blaird466dc42012-07-31 10:42:56 -0700484 self.waitUntilSettled()
485
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400486 self.assertEqual(len(self.builds), 0)
487 self.assertEqual(len(self.history), 11)
488 self.assertEqual(A.data['status'], 'NEW')
489 self.assertEqual(B.data['status'], 'MERGED')
490 self.assertEqual(C.data['status'], 'MERGED')
491 self.assertEqual(A.reported, 2)
492 self.assertEqual(B.reported, 2)
493 self.assertEqual(C.reported, 2)
James E. Blair8c803f82012-07-31 16:25:42 -0700494
James E. Blairfef71632013-09-23 11:15:47 -0700495 def test_two_failed_changes_at_head(self):
496 "Test that changes are reparented correctly if 2 fail at head"
497
498 self.worker.hold_jobs_in_build = True
499 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
500 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
501 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
502 A.addApproval('CRVW', 2)
503 B.addApproval('CRVW', 2)
504 C.addApproval('CRVW', 2)
505
506 self.worker.addFailTest('project-test1', A)
507 self.worker.addFailTest('project-test1', B)
508
509 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
510 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
511 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
512 self.waitUntilSettled()
513
514 self.worker.release('.*-merge')
515 self.waitUntilSettled()
516 self.worker.release('.*-merge')
517 self.waitUntilSettled()
518 self.worker.release('.*-merge')
519 self.waitUntilSettled()
520
521 self.assertEqual(len(self.builds), 6)
522 self.assertEqual(self.builds[0].name, 'project-test1')
523 self.assertEqual(self.builds[1].name, 'project-test2')
524 self.assertEqual(self.builds[2].name, 'project-test1')
525 self.assertEqual(self.builds[3].name, 'project-test2')
526 self.assertEqual(self.builds[4].name, 'project-test1')
527 self.assertEqual(self.builds[5].name, 'project-test2')
528
529 self.assertTrue(self.job_has_changes(self.builds[0], A))
530 self.assertTrue(self.job_has_changes(self.builds[2], A))
531 self.assertTrue(self.job_has_changes(self.builds[2], B))
532 self.assertTrue(self.job_has_changes(self.builds[4], A))
533 self.assertTrue(self.job_has_changes(self.builds[4], B))
534 self.assertTrue(self.job_has_changes(self.builds[4], C))
535
536 # Fail change B first
537 self.release(self.builds[2])
538 self.waitUntilSettled()
539
540 # restart of C after B failure
541 self.worker.release('.*-merge')
542 self.waitUntilSettled()
543
544 self.assertEqual(len(self.builds), 5)
545 self.assertEqual(self.builds[0].name, 'project-test1')
546 self.assertEqual(self.builds[1].name, 'project-test2')
547 self.assertEqual(self.builds[2].name, 'project-test2')
548 self.assertEqual(self.builds[3].name, 'project-test1')
549 self.assertEqual(self.builds[4].name, 'project-test2')
550
551 self.assertTrue(self.job_has_changes(self.builds[1], A))
552 self.assertTrue(self.job_has_changes(self.builds[2], A))
553 self.assertTrue(self.job_has_changes(self.builds[2], B))
554 self.assertTrue(self.job_has_changes(self.builds[4], A))
555 self.assertFalse(self.job_has_changes(self.builds[4], B))
556 self.assertTrue(self.job_has_changes(self.builds[4], C))
557
558 # Finish running all passing jobs for change A
559 self.release(self.builds[1])
560 self.waitUntilSettled()
561 # Fail and report change A
562 self.release(self.builds[0])
563 self.waitUntilSettled()
564
565 # restart of B,C after A failure
566 self.worker.release('.*-merge')
567 self.waitUntilSettled()
568 self.worker.release('.*-merge')
569 self.waitUntilSettled()
570
571 self.assertEqual(len(self.builds), 4)
572 self.assertEqual(self.builds[0].name, 'project-test1') # B
573 self.assertEqual(self.builds[1].name, 'project-test2') # B
574 self.assertEqual(self.builds[2].name, 'project-test1') # C
575 self.assertEqual(self.builds[3].name, 'project-test2') # C
576
577 self.assertFalse(self.job_has_changes(self.builds[1], A))
578 self.assertTrue(self.job_has_changes(self.builds[1], B))
579 self.assertFalse(self.job_has_changes(self.builds[1], C))
580
581 self.assertFalse(self.job_has_changes(self.builds[2], A))
582 # After A failed and B and C restarted, B should be back in
583 # C's tests because it has not failed yet.
584 self.assertTrue(self.job_has_changes(self.builds[2], B))
585 self.assertTrue(self.job_has_changes(self.builds[2], C))
586
587 self.worker.hold_jobs_in_build = False
588 self.worker.release()
589 self.waitUntilSettled()
590
591 self.assertEqual(len(self.builds), 0)
592 self.assertEqual(len(self.history), 21)
593 self.assertEqual(A.data['status'], 'NEW')
594 self.assertEqual(B.data['status'], 'NEW')
595 self.assertEqual(C.data['status'], 'MERGED')
596 self.assertEqual(A.reported, 2)
597 self.assertEqual(B.reported, 2)
598 self.assertEqual(C.reported, 2)
599
James E. Blair8c803f82012-07-31 16:25:42 -0700600 def test_patch_order(self):
601 "Test that dependent patches are tested in the right order"
602 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
603 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
604 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
605 A.addApproval('CRVW', 2)
606 B.addApproval('CRVW', 2)
607 C.addApproval('CRVW', 2)
608
609 M2 = self.fake_gerrit.addFakeChange('org/project', 'master', 'M2')
610 M1 = self.fake_gerrit.addFakeChange('org/project', 'master', 'M1')
611 M2.setMerged()
612 M1.setMerged()
613
614 # C -> B -> A -> M1 -> M2
615 # M2 is here to make sure it is never queried. If it is, it
616 # means zuul is walking down the entire history of merged
617 # changes.
618
619 C.setDependsOn(B, 1)
620 B.setDependsOn(A, 1)
621 A.setDependsOn(M1, 1)
622 M1.setDependsOn(M2, 1)
623
624 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
625
626 self.waitUntilSettled()
627
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400628 self.assertEqual(A.data['status'], 'NEW')
629 self.assertEqual(B.data['status'], 'NEW')
630 self.assertEqual(C.data['status'], 'NEW')
James E. Blair8c803f82012-07-31 16:25:42 -0700631
632 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
633 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
634
635 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400636 self.assertEqual(M2.queried, 0)
637 self.assertEqual(A.data['status'], 'MERGED')
638 self.assertEqual(B.data['status'], 'MERGED')
639 self.assertEqual(C.data['status'], 'MERGED')
640 self.assertEqual(A.reported, 2)
641 self.assertEqual(B.reported, 2)
642 self.assertEqual(C.reported, 2)
James E. Blair8c803f82012-07-31 16:25:42 -0700643
James E. Blair063672f2015-01-29 13:09:12 -0800644 def test_needed_changes_enqueue(self):
645 "Test that a needed change is enqueued ahead"
646 # A Given a git tree like this, if we enqueue
647 # / \ change C, we should walk up and down the tree
648 # B G and enqueue changes in the order ABCDEFG.
649 # /|\ This is also the order that you would get if
650 # *C E F you enqueued changes in the order ABCDEFG, so
651 # / the ordering is stable across re-enqueue events.
652 # D
653
654 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
655 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
656 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
657 D = self.fake_gerrit.addFakeChange('org/project', 'master', 'D')
658 E = self.fake_gerrit.addFakeChange('org/project', 'master', 'E')
659 F = self.fake_gerrit.addFakeChange('org/project', 'master', 'F')
660 G = self.fake_gerrit.addFakeChange('org/project', 'master', 'G')
661 B.setDependsOn(A, 1)
662 C.setDependsOn(B, 1)
663 D.setDependsOn(C, 1)
664 E.setDependsOn(B, 1)
665 F.setDependsOn(B, 1)
666 G.setDependsOn(A, 1)
667
668 A.addApproval('CRVW', 2)
669 B.addApproval('CRVW', 2)
670 C.addApproval('CRVW', 2)
671 D.addApproval('CRVW', 2)
672 E.addApproval('CRVW', 2)
673 F.addApproval('CRVW', 2)
674 G.addApproval('CRVW', 2)
675 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
676
677 self.waitUntilSettled()
678
679 self.assertEqual(A.data['status'], 'NEW')
680 self.assertEqual(B.data['status'], 'NEW')
681 self.assertEqual(C.data['status'], 'NEW')
682 self.assertEqual(D.data['status'], 'NEW')
683 self.assertEqual(E.data['status'], 'NEW')
684 self.assertEqual(F.data['status'], 'NEW')
685 self.assertEqual(G.data['status'], 'NEW')
686
687 # We're about to add approvals to changes without adding the
688 # triggering events to Zuul, so that we can be sure that it is
689 # enqueing the changes based on dependencies, not because of
690 # triggering events. Since it will have the changes cached
691 # already (without approvals), we need to clear the cache
692 # first.
693 source = self.sched.layout.pipelines['gate'].source
694 source.maintainCache([])
695
696 self.worker.hold_jobs_in_build = True
697 A.addApproval('APRV', 1)
698 B.addApproval('APRV', 1)
699 D.addApproval('APRV', 1)
700 E.addApproval('APRV', 1)
701 F.addApproval('APRV', 1)
702 G.addApproval('APRV', 1)
703 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
704
705 for x in range(8):
706 self.worker.release('.*-merge')
707 self.waitUntilSettled()
708 self.worker.hold_jobs_in_build = False
709 self.worker.release()
710 self.waitUntilSettled()
711
712 self.assertEqual(A.data['status'], 'MERGED')
713 self.assertEqual(B.data['status'], 'MERGED')
714 self.assertEqual(C.data['status'], 'MERGED')
715 self.assertEqual(D.data['status'], 'MERGED')
716 self.assertEqual(E.data['status'], 'MERGED')
717 self.assertEqual(F.data['status'], 'MERGED')
718 self.assertEqual(G.data['status'], 'MERGED')
719 self.assertEqual(A.reported, 2)
720 self.assertEqual(B.reported, 2)
721 self.assertEqual(C.reported, 2)
722 self.assertEqual(D.reported, 2)
723 self.assertEqual(E.reported, 2)
724 self.assertEqual(F.reported, 2)
725 self.assertEqual(G.reported, 2)
726 self.assertEqual(self.history[6].changes,
727 '1,1 2,1 3,1 4,1 5,1 6,1 7,1')
728
James E. Blair0e933c52013-07-11 10:18:52 -0700729 def test_trigger_cache(self):
730 "Test that the trigger cache operates correctly"
731 self.worker.hold_jobs_in_build = True
732
733 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
734 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
735 X = self.fake_gerrit.addFakeChange('org/project', 'master', 'X')
736 A.addApproval('CRVW', 2)
737 B.addApproval('CRVW', 2)
738
739 M1 = self.fake_gerrit.addFakeChange('org/project', 'master', 'M1')
740 M1.setMerged()
741
742 B.setDependsOn(A, 1)
743 A.setDependsOn(M1, 1)
744
745 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
746 self.fake_gerrit.addEvent(X.getPatchsetCreatedEvent(1))
747
748 self.waitUntilSettled()
749
750 for build in self.builds:
751 if build.parameters['ZUUL_PIPELINE'] == 'check':
752 build.release()
753 self.waitUntilSettled()
754 for build in self.builds:
755 if build.parameters['ZUUL_PIPELINE'] == 'check':
756 build.release()
757 self.waitUntilSettled()
758
759 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
760 self.waitUntilSettled()
761
Antoine Mussof0506fa2014-06-03 15:03:38 +0200762 self.log.debug("len %s" % self.gerrit._change_cache.keys())
James E. Blair0e933c52013-07-11 10:18:52 -0700763 # there should still be changes in the cache
James E. Blair6c358e72013-07-29 17:06:47 -0700764 self.assertNotEqual(len(self.gerrit._change_cache.keys()), 0)
James E. Blair0e933c52013-07-11 10:18:52 -0700765
766 self.worker.hold_jobs_in_build = False
767 self.worker.release()
768 self.waitUntilSettled()
769
770 self.assertEqual(A.data['status'], 'MERGED')
771 self.assertEqual(B.data['status'], 'MERGED')
772 self.assertEqual(A.queried, 2) # Initial and isMerged
773 self.assertEqual(B.queried, 3) # Initial A, refresh from B, isMerged
774
James E. Blair8c803f82012-07-31 16:25:42 -0700775 def test_can_merge(self):
James E. Blair4886cc12012-07-18 15:39:41 -0700776 "Test whether a change is ready to merge"
James E. Blair8c803f82012-07-31 16:25:42 -0700777 # TODO: move to test_gerrit (this is a unit test!)
778 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
James E. Blairc0dedf82014-08-06 09:37:52 -0700779 source = self.sched.layout.pipelines['gate'].source
780 a = source._getChange(1, 2)
James E. Blaireff88162013-07-01 12:44:14 -0400781 mgr = self.sched.layout.pipelines['gate'].manager
James E. Blairc0dedf82014-08-06 09:37:52 -0700782 self.assertFalse(source.canMerge(a, mgr.getSubmitAllowNeeds()))
James E. Blair8c803f82012-07-31 16:25:42 -0700783
784 A.addApproval('CRVW', 2)
James E. Blairc0dedf82014-08-06 09:37:52 -0700785 a = source._getChange(1, 2, refresh=True)
786 self.assertFalse(source.canMerge(a, mgr.getSubmitAllowNeeds()))
James E. Blair8c803f82012-07-31 16:25:42 -0700787
788 A.addApproval('APRV', 1)
James E. Blairc0dedf82014-08-06 09:37:52 -0700789 a = source._getChange(1, 2, refresh=True)
790 self.assertTrue(source.canMerge(a, mgr.getSubmitAllowNeeds()))
791 source.maintainCache([])
James E. Blair4886cc12012-07-18 15:39:41 -0700792
793 def test_build_configuration(self):
794 "Test that zuul merges the right commits for testing"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700795
796 self.gearman_server.hold_jobs_in_queue = True
James E. Blair4886cc12012-07-18 15:39:41 -0700797 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
798 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
799 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
800 A.addApproval('CRVW', 2)
801 B.addApproval('CRVW', 2)
802 C.addApproval('CRVW', 2)
803 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
804 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
805 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
806 self.waitUntilSettled()
807
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700808 self.gearman_server.release('.*-merge')
James E. Blair4886cc12012-07-18 15:39:41 -0700809 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700810 self.gearman_server.release('.*-merge')
James E. Blair4886cc12012-07-18 15:39:41 -0700811 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700812 self.gearman_server.release('.*-merge')
James E. Blair4886cc12012-07-18 15:39:41 -0700813 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -0700814 queue = self.gearman_server.getQueue()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700815 ref = self.getParameter(queue[-1], 'ZUUL_REF')
816 self.gearman_server.hold_jobs_in_queue = False
817 self.gearman_server.release()
James E. Blair973721f2012-08-15 10:19:43 -0700818 self.waitUntilSettled()
James E. Blair4886cc12012-07-18 15:39:41 -0700819
Monty Taylorbc758832013-06-17 17:22:42 -0400820 path = os.path.join(self.git_root, "org/project")
James E. Blair4886cc12012-07-18 15:39:41 -0700821 repo = git.Repo(path)
822 repo_messages = [c.message.strip() for c in repo.iter_commits(ref)]
823 repo_messages.reverse()
James E. Blair4886cc12012-07-18 15:39:41 -0700824 correct_messages = ['initial commit', 'A-1', 'B-1', 'C-1']
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400825 self.assertEqual(repo_messages, correct_messages)
James E. Blair973721f2012-08-15 10:19:43 -0700826
827 def test_build_configuration_conflict(self):
828 "Test that merge conflicts are handled"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700829
830 self.gearman_server.hold_jobs_in_queue = True
James E. Blair6736beb2013-07-11 15:18:15 -0700831 A = self.fake_gerrit.addFakeChange('org/conflict-project',
832 'master', 'A')
James E. Blair973721f2012-08-15 10:19:43 -0700833 A.addPatchset(['conflict'])
James E. Blair6736beb2013-07-11 15:18:15 -0700834 B = self.fake_gerrit.addFakeChange('org/conflict-project',
835 'master', 'B')
James E. Blair973721f2012-08-15 10:19:43 -0700836 B.addPatchset(['conflict'])
James E. Blair6736beb2013-07-11 15:18:15 -0700837 C = self.fake_gerrit.addFakeChange('org/conflict-project',
838 'master', 'C')
James E. Blair973721f2012-08-15 10:19:43 -0700839 A.addApproval('CRVW', 2)
840 B.addApproval('CRVW', 2)
841 C.addApproval('CRVW', 2)
842 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
843 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
844 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
845 self.waitUntilSettled()
846
James E. Blair6736beb2013-07-11 15:18:15 -0700847 self.assertEqual(A.reported, 1)
848 self.assertEqual(B.reported, 1)
849 self.assertEqual(C.reported, 1)
850
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700851 self.gearman_server.release('.*-merge')
James E. Blair973721f2012-08-15 10:19:43 -0700852 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700853 self.gearman_server.release('.*-merge')
James E. Blair973721f2012-08-15 10:19:43 -0700854 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700855 self.gearman_server.release('.*-merge')
James E. Blair973721f2012-08-15 10:19:43 -0700856 self.waitUntilSettled()
James E. Blair972e3c72013-08-29 12:04:55 -0700857
858 self.assertEqual(len(self.history), 2) # A and C merge jobs
859
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700860 self.gearman_server.hold_jobs_in_queue = False
861 self.gearman_server.release()
James E. Blair973721f2012-08-15 10:19:43 -0700862 self.waitUntilSettled()
863
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400864 self.assertEqual(A.data['status'], 'MERGED')
865 self.assertEqual(B.data['status'], 'NEW')
866 self.assertEqual(C.data['status'], 'MERGED')
867 self.assertEqual(A.reported, 2)
868 self.assertEqual(B.reported, 2)
869 self.assertEqual(C.reported, 2)
James E. Blair972e3c72013-08-29 12:04:55 -0700870 self.assertEqual(len(self.history), 6)
James E. Blair6736beb2013-07-11 15:18:15 -0700871
James E. Blairdaabed22012-08-15 15:38:57 -0700872 def test_post(self):
873 "Test that post jobs run"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700874
Zhongyue Luo5d556072012-09-21 02:00:47 +0900875 e = {
876 "type": "ref-updated",
877 "submitter": {
878 "name": "User Name",
879 },
880 "refUpdate": {
881 "oldRev": "90f173846e3af9154517b88543ffbd1691f31366",
882 "newRev": "d479a0bfcb34da57a31adb2a595c0cf687812543",
883 "refName": "master",
884 "project": "org/project",
885 }
886 }
James E. Blairdaabed22012-08-15 15:38:57 -0700887 self.fake_gerrit.addEvent(e)
888 self.waitUntilSettled()
889
Monty Taylor6bef8ef2013-06-02 08:17:12 -0400890 job_names = [x.name for x in self.history]
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400891 self.assertEqual(len(self.history), 1)
892 self.assertIn('project-post', job_names)
James E. Blairc6294a52012-08-17 10:19:48 -0700893
894 def test_build_configuration_branch(self):
895 "Test that the right commits are on alternate branches"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700896
897 self.gearman_server.hold_jobs_in_queue = True
James E. Blairc6294a52012-08-17 10:19:48 -0700898 A = self.fake_gerrit.addFakeChange('org/project', 'mp', 'A')
899 B = self.fake_gerrit.addFakeChange('org/project', 'mp', 'B')
900 C = self.fake_gerrit.addFakeChange('org/project', 'mp', 'C')
901 A.addApproval('CRVW', 2)
902 B.addApproval('CRVW', 2)
903 C.addApproval('CRVW', 2)
904 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
905 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
906 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
907 self.waitUntilSettled()
908
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700909 self.gearman_server.release('.*-merge')
James E. Blairc6294a52012-08-17 10:19:48 -0700910 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700911 self.gearman_server.release('.*-merge')
James E. Blairc6294a52012-08-17 10:19:48 -0700912 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700913 self.gearman_server.release('.*-merge')
James E. Blairc6294a52012-08-17 10:19:48 -0700914 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -0700915 queue = self.gearman_server.getQueue()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700916 ref = self.getParameter(queue[-1], 'ZUUL_REF')
917 self.gearman_server.hold_jobs_in_queue = False
918 self.gearman_server.release()
James E. Blairc6294a52012-08-17 10:19:48 -0700919 self.waitUntilSettled()
920
Monty Taylorbc758832013-06-17 17:22:42 -0400921 path = os.path.join(self.git_root, "org/project")
James E. Blairc6294a52012-08-17 10:19:48 -0700922 repo = git.Repo(path)
923 repo_messages = [c.message.strip() for c in repo.iter_commits(ref)]
924 repo_messages.reverse()
James E. Blairc6294a52012-08-17 10:19:48 -0700925 correct_messages = ['initial commit', 'mp commit', 'A-1', 'B-1', 'C-1']
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400926 self.assertEqual(repo_messages, correct_messages)
James E. Blairc6294a52012-08-17 10:19:48 -0700927
928 def test_build_configuration_branch_interaction(self):
929 "Test that switching between branches works"
930 self.test_build_configuration()
931 self.test_build_configuration_branch()
932 # C has been merged, undo that
Monty Taylorbc758832013-06-17 17:22:42 -0400933 path = os.path.join(self.upstream_root, "org/project")
James E. Blairc6294a52012-08-17 10:19:48 -0700934 repo = git.Repo(path)
935 repo.heads.master.commit = repo.commit('init')
936 self.test_build_configuration()
937
938 def test_build_configuration_multi_branch(self):
939 "Test that dependent changes on multiple branches are merged"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700940
941 self.gearman_server.hold_jobs_in_queue = True
James E. Blairc6294a52012-08-17 10:19:48 -0700942 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
943 B = self.fake_gerrit.addFakeChange('org/project', 'mp', 'B')
944 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
945 A.addApproval('CRVW', 2)
946 B.addApproval('CRVW', 2)
947 C.addApproval('CRVW', 2)
948 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
949 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
950 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
951 self.waitUntilSettled()
James E. Blairbb1fe502014-03-04 10:15:06 -0800952 queue = self.gearman_server.getQueue()
953 job_A = None
954 for job in queue:
955 if 'project-merge' in job.name:
956 job_A = job
957 ref_A = self.getParameter(job_A, 'ZUUL_REF')
958 commit_A = self.getParameter(job_A, 'ZUUL_COMMIT')
959 self.log.debug("Got Zuul ref for change A: %s" % ref_A)
960 self.log.debug("Got Zuul commit for change A: %s" % commit_A)
James E. Blairc6294a52012-08-17 10:19:48 -0700961
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700962 self.gearman_server.release('.*-merge')
James E. Blairc6294a52012-08-17 10:19:48 -0700963 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -0700964 queue = self.gearman_server.getQueue()
James E. Blaird320d7e2013-07-30 16:36:20 -0700965 job_B = None
966 for job in queue:
967 if 'project-merge' in job.name:
968 job_B = job
969 ref_B = self.getParameter(job_B, 'ZUUL_REF')
James E. Blairbb1fe502014-03-04 10:15:06 -0800970 commit_B = self.getParameter(job_B, 'ZUUL_COMMIT')
James E. Blairf750aa02013-07-15 14:11:24 -0700971 self.log.debug("Got Zuul ref for change B: %s" % ref_B)
James E. Blairbb1fe502014-03-04 10:15:06 -0800972 self.log.debug("Got Zuul commit for change B: %s" % commit_B)
973
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700974 self.gearman_server.release('.*-merge')
James E. Blairc6294a52012-08-17 10:19:48 -0700975 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -0700976 queue = self.gearman_server.getQueue()
James E. Blaird320d7e2013-07-30 16:36:20 -0700977 for job in queue:
978 if 'project-merge' in job.name:
979 job_C = job
980 ref_C = self.getParameter(job_C, 'ZUUL_REF')
James E. Blairbb1fe502014-03-04 10:15:06 -0800981 commit_C = self.getParameter(job_C, 'ZUUL_COMMIT')
James E. Blairf750aa02013-07-15 14:11:24 -0700982 self.log.debug("Got Zuul ref for change C: %s" % ref_C)
James E. Blairbb1fe502014-03-04 10:15:06 -0800983 self.log.debug("Got Zuul commit for change C: %s" % commit_C)
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700984 self.gearman_server.hold_jobs_in_queue = False
985 self.gearman_server.release()
James E. Blairc6294a52012-08-17 10:19:48 -0700986 self.waitUntilSettled()
987
Monty Taylorbc758832013-06-17 17:22:42 -0400988 path = os.path.join(self.git_root, "org/project")
James E. Blairc6294a52012-08-17 10:19:48 -0700989 repo = git.Repo(path)
990
991 repo_messages = [c.message.strip()
James E. Blairf750aa02013-07-15 14:11:24 -0700992 for c in repo.iter_commits(ref_C)]
James E. Blairbb1fe502014-03-04 10:15:06 -0800993 repo_shas = [c.hexsha for c in repo.iter_commits(ref_C)]
James E. Blairc6294a52012-08-17 10:19:48 -0700994 repo_messages.reverse()
James E. Blairc6294a52012-08-17 10:19:48 -0700995 correct_messages = ['initial commit', 'A-1', 'C-1']
James E. Blairbb1fe502014-03-04 10:15:06 -0800996 # Ensure the right commits are in the history for this ref
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400997 self.assertEqual(repo_messages, correct_messages)
James E. Blairbb1fe502014-03-04 10:15:06 -0800998 # Ensure ZUUL_REF -> ZUUL_COMMIT
999 self.assertEqual(repo_shas[0], commit_C)
James E. Blairc6294a52012-08-17 10:19:48 -07001000
1001 repo_messages = [c.message.strip()
James E. Blairf750aa02013-07-15 14:11:24 -07001002 for c in repo.iter_commits(ref_B)]
James E. Blairbb1fe502014-03-04 10:15:06 -08001003 repo_shas = [c.hexsha for c in repo.iter_commits(ref_B)]
James E. Blairc6294a52012-08-17 10:19:48 -07001004 repo_messages.reverse()
James E. Blairc6294a52012-08-17 10:19:48 -07001005 correct_messages = ['initial commit', 'mp commit', 'B-1']
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001006 self.assertEqual(repo_messages, correct_messages)
James E. Blairbb1fe502014-03-04 10:15:06 -08001007 self.assertEqual(repo_shas[0], commit_B)
1008
1009 repo_messages = [c.message.strip()
1010 for c in repo.iter_commits(ref_A)]
1011 repo_shas = [c.hexsha for c in repo.iter_commits(ref_A)]
1012 repo_messages.reverse()
1013 correct_messages = ['initial commit', 'A-1']
1014 self.assertEqual(repo_messages, correct_messages)
1015 self.assertEqual(repo_shas[0], commit_A)
1016
1017 self.assertNotEqual(ref_A, ref_B, ref_C)
1018 self.assertNotEqual(commit_A, commit_B, commit_C)
James E. Blair7f71c802012-08-22 13:04:32 -07001019
1020 def test_one_job_project(self):
1021 "Test that queueing works with one job"
1022 A = self.fake_gerrit.addFakeChange('org/one-job-project',
1023 'master', 'A')
1024 B = self.fake_gerrit.addFakeChange('org/one-job-project',
1025 'master', 'B')
1026 A.addApproval('CRVW', 2)
1027 B.addApproval('CRVW', 2)
1028 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1029 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1030 self.waitUntilSettled()
1031
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001032 self.assertEqual(A.data['status'], 'MERGED')
1033 self.assertEqual(A.reported, 2)
1034 self.assertEqual(B.data['status'], 'MERGED')
1035 self.assertEqual(B.reported, 2)
James E. Blaircaec0c52012-08-22 14:52:22 -07001036
Antoine Musso80edd5a2013-02-13 15:37:53 +01001037 def test_job_from_templates_launched(self):
1038 "Test whether a job generated via a template can be launched"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001039
Antoine Musso80edd5a2013-02-13 15:37:53 +01001040 A = self.fake_gerrit.addFakeChange(
1041 'org/templated-project', 'master', 'A')
1042 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1043 self.waitUntilSettled()
Antoine Musso80edd5a2013-02-13 15:37:53 +01001044
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001045 self.assertEqual(self.getJobFromHistory('project-test1').result,
1046 'SUCCESS')
1047 self.assertEqual(self.getJobFromHistory('project-test2').result,
1048 'SUCCESS')
Antoine Musso80edd5a2013-02-13 15:37:53 +01001049
James E. Blair3e98c022013-12-16 15:25:38 -08001050 def test_layered_templates(self):
1051 "Test whether a job generated via a template can be launched"
1052
1053 A = self.fake_gerrit.addFakeChange(
1054 'org/layered-project', 'master', 'A')
1055 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1056 self.waitUntilSettled()
1057
1058 self.assertEqual(self.getJobFromHistory('project-test1').result,
1059 'SUCCESS')
1060 self.assertEqual(self.getJobFromHistory('project-test2').result,
1061 'SUCCESS')
James E. Blairaea6cf62013-12-16 15:38:12 -08001062 self.assertEqual(self.getJobFromHistory('layered-project-test3'
1063 ).result, 'SUCCESS')
1064 self.assertEqual(self.getJobFromHistory('layered-project-test4'
1065 ).result, 'SUCCESS')
James E. Blair12a92b12014-03-26 11:54:53 -07001066 self.assertEqual(self.getJobFromHistory('layered-project-foo-test5'
1067 ).result, 'SUCCESS')
James E. Blair3e98c022013-12-16 15:25:38 -08001068 self.assertEqual(self.getJobFromHistory('project-test6').result,
1069 'SUCCESS')
1070
James E. Blaircaec0c52012-08-22 14:52:22 -07001071 def test_dependent_changes_dequeue(self):
1072 "Test that dependent patches are not needlessly tested"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001073
James E. Blaircaec0c52012-08-22 14:52:22 -07001074 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1075 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1076 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1077 A.addApproval('CRVW', 2)
1078 B.addApproval('CRVW', 2)
1079 C.addApproval('CRVW', 2)
1080
1081 M1 = self.fake_gerrit.addFakeChange('org/project', 'master', 'M1')
1082 M1.setMerged()
1083
1084 # C -> B -> A -> M1
1085
1086 C.setDependsOn(B, 1)
1087 B.setDependsOn(A, 1)
1088 A.setDependsOn(M1, 1)
1089
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001090 self.worker.addFailTest('project-merge', A)
James E. Blaircaec0c52012-08-22 14:52:22 -07001091
1092 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1093 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1094 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1095
1096 self.waitUntilSettled()
1097
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001098 self.assertEqual(A.data['status'], 'NEW')
1099 self.assertEqual(A.reported, 2)
1100 self.assertEqual(B.data['status'], 'NEW')
1101 self.assertEqual(B.reported, 2)
1102 self.assertEqual(C.data['status'], 'NEW')
1103 self.assertEqual(C.reported, 2)
1104 self.assertEqual(len(self.history), 1)
James E. Blairec590122012-08-22 15:19:31 -07001105
James E. Blair972e3c72013-08-29 12:04:55 -07001106 def test_failing_dependent_changes(self):
1107 "Test that failing dependent patches are taken out of stream"
1108 self.worker.hold_jobs_in_build = True
1109 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1110 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1111 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1112 D = self.fake_gerrit.addFakeChange('org/project', 'master', 'D')
1113 E = self.fake_gerrit.addFakeChange('org/project', 'master', 'E')
1114 A.addApproval('CRVW', 2)
1115 B.addApproval('CRVW', 2)
1116 C.addApproval('CRVW', 2)
1117 D.addApproval('CRVW', 2)
1118 E.addApproval('CRVW', 2)
1119
1120 # E, D -> C -> B, A
1121
1122 D.setDependsOn(C, 1)
1123 C.setDependsOn(B, 1)
1124
1125 self.worker.addFailTest('project-test1', B)
1126
1127 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1128 self.fake_gerrit.addEvent(D.addApproval('APRV', 1))
1129 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1130 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1131 self.fake_gerrit.addEvent(E.addApproval('APRV', 1))
1132
1133 self.waitUntilSettled()
1134 self.worker.release('.*-merge')
1135 self.waitUntilSettled()
1136 self.worker.release('.*-merge')
1137 self.waitUntilSettled()
1138 self.worker.release('.*-merge')
1139 self.waitUntilSettled()
1140 self.worker.release('.*-merge')
1141 self.waitUntilSettled()
1142 self.worker.release('.*-merge')
1143 self.waitUntilSettled()
1144
1145 self.worker.hold_jobs_in_build = False
1146 for build in self.builds:
1147 if build.parameters['ZUUL_CHANGE'] != '1':
1148 build.release()
1149 self.waitUntilSettled()
1150
1151 self.worker.release()
1152 self.waitUntilSettled()
1153
1154 self.assertEqual(A.data['status'], 'MERGED')
1155 self.assertEqual(A.reported, 2)
Jeremy Stanley10837132014-08-02 16:10:56 +00001156 self.assertIn('Build succeeded', A.messages[1])
James E. Blair972e3c72013-08-29 12:04:55 -07001157 self.assertEqual(B.data['status'], 'NEW')
1158 self.assertEqual(B.reported, 2)
Jeremy Stanley10837132014-08-02 16:10:56 +00001159 self.assertIn('Build failed', B.messages[1])
James E. Blair972e3c72013-08-29 12:04:55 -07001160 self.assertEqual(C.data['status'], 'NEW')
1161 self.assertEqual(C.reported, 2)
Jeremy Stanley10837132014-08-02 16:10:56 +00001162 self.assertIn('depends on a change', C.messages[1])
James E. Blair972e3c72013-08-29 12:04:55 -07001163 self.assertEqual(D.data['status'], 'NEW')
1164 self.assertEqual(D.reported, 2)
Jeremy Stanley10837132014-08-02 16:10:56 +00001165 self.assertIn('depends on a change', D.messages[1])
James E. Blair972e3c72013-08-29 12:04:55 -07001166 self.assertEqual(E.data['status'], 'MERGED')
1167 self.assertEqual(E.reported, 2)
Jeremy Stanley10837132014-08-02 16:10:56 +00001168 self.assertIn('Build succeeded', E.messages[1])
James E. Blair972e3c72013-08-29 12:04:55 -07001169 self.assertEqual(len(self.history), 18)
1170
James E. Blairec590122012-08-22 15:19:31 -07001171 def test_head_is_dequeued_once(self):
James E. Blair2fa50962013-01-30 21:50:41 -08001172 "Test that if a change at the head fails it is dequeued only once"
James E. Blairec590122012-08-22 15:19:31 -07001173 # If it's dequeued more than once, we should see extra
1174 # aborted jobs.
James E. Blairec590122012-08-22 15:19:31 -07001175
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001176 self.worker.hold_jobs_in_build = True
James E. Blairec590122012-08-22 15:19:31 -07001177 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
1178 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
1179 C = self.fake_gerrit.addFakeChange('org/project1', 'master', 'C')
1180 A.addApproval('CRVW', 2)
1181 B.addApproval('CRVW', 2)
1182 C.addApproval('CRVW', 2)
1183
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001184 self.worker.addFailTest('project1-test1', A)
1185 self.worker.addFailTest('project1-test2', A)
1186 self.worker.addFailTest('project1-project2-integration', A)
James E. Blairec590122012-08-22 15:19:31 -07001187
1188 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1189 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1190 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1191
1192 self.waitUntilSettled()
James E. Blairec590122012-08-22 15:19:31 -07001193
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001194 self.assertEqual(len(self.builds), 1)
1195 self.assertEqual(self.builds[0].name, 'project1-merge')
1196 self.assertTrue(self.job_has_changes(self.builds[0], A))
James E. Blairec590122012-08-22 15:19:31 -07001197
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001198 self.worker.release('.*-merge')
James E. Blairec590122012-08-22 15:19:31 -07001199 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001200 self.worker.release('.*-merge')
James E. Blairec590122012-08-22 15:19:31 -07001201 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001202 self.worker.release('.*-merge')
James E. Blairec590122012-08-22 15:19:31 -07001203 self.waitUntilSettled()
1204
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001205 self.assertEqual(len(self.builds), 9)
1206 self.assertEqual(self.builds[0].name, 'project1-test1')
1207 self.assertEqual(self.builds[1].name, 'project1-test2')
1208 self.assertEqual(self.builds[2].name, 'project1-project2-integration')
1209 self.assertEqual(self.builds[3].name, 'project1-test1')
1210 self.assertEqual(self.builds[4].name, 'project1-test2')
1211 self.assertEqual(self.builds[5].name, 'project1-project2-integration')
1212 self.assertEqual(self.builds[6].name, 'project1-test1')
1213 self.assertEqual(self.builds[7].name, 'project1-test2')
1214 self.assertEqual(self.builds[8].name, 'project1-project2-integration')
James E. Blairec590122012-08-22 15:19:31 -07001215
Monty Taylor6bef8ef2013-06-02 08:17:12 -04001216 self.release(self.builds[0])
James E. Blairec590122012-08-22 15:19:31 -07001217 self.waitUntilSettled()
1218
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001219 self.assertEqual(len(self.builds), 3) # test2,integration, merge for B
1220 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 6)
James E. Blairec590122012-08-22 15:19:31 -07001221
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001222 self.worker.hold_jobs_in_build = False
1223 self.worker.release()
James E. Blairec590122012-08-22 15:19:31 -07001224 self.waitUntilSettled()
1225
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001226 self.assertEqual(len(self.builds), 0)
1227 self.assertEqual(len(self.history), 20)
James E. Blaircaec0c52012-08-22 14:52:22 -07001228
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001229 self.assertEqual(A.data['status'], 'NEW')
1230 self.assertEqual(B.data['status'], 'MERGED')
1231 self.assertEqual(C.data['status'], 'MERGED')
1232 self.assertEqual(A.reported, 2)
1233 self.assertEqual(B.reported, 2)
1234 self.assertEqual(C.reported, 2)
James E. Blair4ec821f2012-08-23 15:28:28 -07001235
1236 def test_nonvoting_job(self):
1237 "Test that non-voting jobs don't vote."
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001238
James E. Blair4ec821f2012-08-23 15:28:28 -07001239 A = self.fake_gerrit.addFakeChange('org/nonvoting-project',
1240 'master', 'A')
1241 A.addApproval('CRVW', 2)
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001242 self.worker.addFailTest('nonvoting-project-test2', A)
James E. Blair4ec821f2012-08-23 15:28:28 -07001243 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1244
1245 self.waitUntilSettled()
James E. Blair4ec821f2012-08-23 15:28:28 -07001246
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001247 self.assertEqual(A.data['status'], 'MERGED')
1248 self.assertEqual(A.reported, 2)
1249 self.assertEqual(
1250 self.getJobFromHistory('nonvoting-project-merge').result,
1251 'SUCCESS')
1252 self.assertEqual(
1253 self.getJobFromHistory('nonvoting-project-test1').result,
1254 'SUCCESS')
1255 self.assertEqual(
1256 self.getJobFromHistory('nonvoting-project-test2').result,
1257 'FAILURE')
James E. Blaire0487072012-08-29 17:38:31 -07001258
1259 def test_check_queue_success(self):
1260 "Test successful check queue jobs."
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001261
James E. Blaire0487072012-08-29 17:38:31 -07001262 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1263 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1264
1265 self.waitUntilSettled()
James E. Blaire0487072012-08-29 17:38:31 -07001266
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001267 self.assertEqual(A.data['status'], 'NEW')
1268 self.assertEqual(A.reported, 1)
1269 self.assertEqual(self.getJobFromHistory('project-merge').result,
1270 'SUCCESS')
1271 self.assertEqual(self.getJobFromHistory('project-test1').result,
1272 'SUCCESS')
1273 self.assertEqual(self.getJobFromHistory('project-test2').result,
1274 'SUCCESS')
James E. Blaire0487072012-08-29 17:38:31 -07001275
1276 def test_check_queue_failure(self):
1277 "Test failed check queue jobs."
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001278
James E. Blaire0487072012-08-29 17:38:31 -07001279 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001280 self.worker.addFailTest('project-test2', A)
James E. Blaire0487072012-08-29 17:38:31 -07001281 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1282
1283 self.waitUntilSettled()
James E. Blaire0487072012-08-29 17:38:31 -07001284
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001285 self.assertEqual(A.data['status'], 'NEW')
1286 self.assertEqual(A.reported, 1)
1287 self.assertEqual(self.getJobFromHistory('project-merge').result,
James E. Blair78e31b32013-07-09 09:11:34 -07001288 'SUCCESS')
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001289 self.assertEqual(self.getJobFromHistory('project-test1').result,
1290 'SUCCESS')
1291 self.assertEqual(self.getJobFromHistory('project-test2').result,
1292 'FAILURE')
James E. Blair127bc182012-08-28 15:55:15 -07001293
1294 def test_dependent_behind_dequeue(self):
1295 "test that dependent changes behind dequeued changes work"
1296 # This complicated test is a reproduction of a real life bug
1297 self.sched.reconfigure(self.config)
James E. Blair127bc182012-08-28 15:55:15 -07001298
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001299 self.worker.hold_jobs_in_build = True
James E. Blair127bc182012-08-28 15:55:15 -07001300 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
1301 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
1302 C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
1303 D = self.fake_gerrit.addFakeChange('org/project2', 'master', 'D')
1304 E = self.fake_gerrit.addFakeChange('org/project2', 'master', 'E')
1305 F = self.fake_gerrit.addFakeChange('org/project3', 'master', 'F')
1306 D.setDependsOn(C, 1)
1307 E.setDependsOn(D, 1)
1308 A.addApproval('CRVW', 2)
1309 B.addApproval('CRVW', 2)
1310 C.addApproval('CRVW', 2)
1311 D.addApproval('CRVW', 2)
1312 E.addApproval('CRVW', 2)
1313 F.addApproval('CRVW', 2)
1314
1315 A.fail_merge = True
James E. Blair127bc182012-08-28 15:55:15 -07001316
1317 # Change object re-use in the gerrit trigger is hidden if
1318 # changes are added in quick succession; waiting makes it more
1319 # like real life.
1320 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1321 self.waitUntilSettled()
1322 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1323 self.waitUntilSettled()
1324
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001325 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001326 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001327 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001328 self.waitUntilSettled()
1329
1330 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1331 self.waitUntilSettled()
1332 self.fake_gerrit.addEvent(D.addApproval('APRV', 1))
1333 self.waitUntilSettled()
1334 self.fake_gerrit.addEvent(E.addApproval('APRV', 1))
1335 self.waitUntilSettled()
1336 self.fake_gerrit.addEvent(F.addApproval('APRV', 1))
1337 self.waitUntilSettled()
1338
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001339 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001340 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001341 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001342 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001343 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001344 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001345 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001346 self.waitUntilSettled()
1347
1348 # all jobs running
James E. Blaire955e062012-10-08 09:49:03 -07001349
1350 # Grab pointers to the jobs we want to release before
1351 # releasing any, because list indexes may change as
1352 # the jobs complete.
Monty Taylor6bef8ef2013-06-02 08:17:12 -04001353 a, b, c = self.builds[:3]
James E. Blaire955e062012-10-08 09:49:03 -07001354 a.release()
1355 b.release()
1356 c.release()
James E. Blair127bc182012-08-28 15:55:15 -07001357 self.waitUntilSettled()
1358
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001359 self.worker.hold_jobs_in_build = False
1360 self.worker.release()
James E. Blair127bc182012-08-28 15:55:15 -07001361 self.waitUntilSettled()
1362
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001363 self.assertEqual(A.data['status'], 'NEW')
1364 self.assertEqual(B.data['status'], 'MERGED')
1365 self.assertEqual(C.data['status'], 'MERGED')
1366 self.assertEqual(D.data['status'], 'MERGED')
1367 self.assertEqual(E.data['status'], 'MERGED')
1368 self.assertEqual(F.data['status'], 'MERGED')
James E. Blair127bc182012-08-28 15:55:15 -07001369
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001370 self.assertEqual(A.reported, 2)
1371 self.assertEqual(B.reported, 2)
1372 self.assertEqual(C.reported, 2)
1373 self.assertEqual(D.reported, 2)
1374 self.assertEqual(E.reported, 2)
1375 self.assertEqual(F.reported, 2)
James E. Blair127bc182012-08-28 15:55:15 -07001376
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001377 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 15)
1378 self.assertEqual(len(self.history), 44)
James E. Blair05fed602012-09-07 12:45:24 -07001379
1380 def test_merger_repack(self):
1381 "Test that the merger works after a repack"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001382
James E. Blair05fed602012-09-07 12:45:24 -07001383 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1384 A.addApproval('CRVW', 2)
1385 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1386 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001387 self.assertEqual(self.getJobFromHistory('project-merge').result,
1388 'SUCCESS')
1389 self.assertEqual(self.getJobFromHistory('project-test1').result,
1390 'SUCCESS')
1391 self.assertEqual(self.getJobFromHistory('project-test2').result,
1392 'SUCCESS')
1393 self.assertEqual(A.data['status'], 'MERGED')
1394 self.assertEqual(A.reported, 2)
James E. Blair05fed602012-09-07 12:45:24 -07001395 self.assertEmptyQueues()
James E. Blair4ca985f2013-05-30 12:27:43 -07001396 self.worker.build_history = []
James E. Blair05fed602012-09-07 12:45:24 -07001397
Monty Taylorbc758832013-06-17 17:22:42 -04001398 path = os.path.join(self.git_root, "org/project")
1399 print repack_repo(path)
James E. Blair05fed602012-09-07 12:45:24 -07001400
1401 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1402 A.addApproval('CRVW', 2)
1403 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1404 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001405 self.assertEqual(self.getJobFromHistory('project-merge').result,
1406 'SUCCESS')
1407 self.assertEqual(self.getJobFromHistory('project-test1').result,
1408 'SUCCESS')
1409 self.assertEqual(self.getJobFromHistory('project-test2').result,
1410 'SUCCESS')
1411 self.assertEqual(A.data['status'], 'MERGED')
1412 self.assertEqual(A.reported, 2)
James E. Blair7ee88a22012-09-12 18:59:31 +02001413
James E. Blair4886f282012-11-15 09:27:33 -08001414 def test_merger_repack_large_change(self):
1415 "Test that the merger works with large changes after a repack"
1416 # https://bugs.launchpad.net/zuul/+bug/1078946
James E. Blairac2c3242014-01-24 13:38:51 -08001417 # This test assumes the repo is already cloned; make sure it is
1418 url = self.sched.triggers['gerrit'].getGitUrl(
1419 self.sched.layout.projects['org/project1'])
James E. Blair4076e2b2014-01-28 12:42:20 -08001420 self.merge_server.merger.addProject('org/project1', url)
James E. Blair4886f282012-11-15 09:27:33 -08001421 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
1422 A.addPatchset(large=True)
Monty Taylorbc758832013-06-17 17:22:42 -04001423 path = os.path.join(self.upstream_root, "org/project1")
1424 print repack_repo(path)
1425 path = os.path.join(self.git_root, "org/project1")
1426 print repack_repo(path)
James E. Blair4886f282012-11-15 09:27:33 -08001427
1428 A.addApproval('CRVW', 2)
1429 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1430 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001431 self.assertEqual(self.getJobFromHistory('project1-merge').result,
1432 'SUCCESS')
1433 self.assertEqual(self.getJobFromHistory('project1-test1').result,
1434 'SUCCESS')
1435 self.assertEqual(self.getJobFromHistory('project1-test2').result,
1436 'SUCCESS')
1437 self.assertEqual(A.data['status'], 'MERGED')
1438 self.assertEqual(A.reported, 2)
James E. Blair4886f282012-11-15 09:27:33 -08001439
James E. Blair7ee88a22012-09-12 18:59:31 +02001440 def test_nonexistent_job(self):
1441 "Test launching a job that doesn't exist"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001442 # Set to the state immediately after a restart
1443 self.resetGearmanServer()
1444 self.launcher.negative_function_cache_ttl = 0
James E. Blair7ee88a22012-09-12 18:59:31 +02001445
1446 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1447 A.addApproval('CRVW', 2)
1448 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1449 # There may be a thread about to report a lost change
1450 while A.reported < 2:
1451 self.waitUntilSettled()
Monty Taylor6bef8ef2013-06-02 08:17:12 -04001452 job_names = [x.name for x in self.history]
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001453 self.assertFalse(job_names)
1454 self.assertEqual(A.data['status'], 'NEW')
1455 self.assertEqual(A.reported, 2)
James E. Blair7ee88a22012-09-12 18:59:31 +02001456 self.assertEmptyQueues()
1457
1458 # Make sure things still work:
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001459 self.registerJobs()
James E. Blair7ee88a22012-09-12 18:59:31 +02001460 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1461 A.addApproval('CRVW', 2)
1462 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1463 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001464 self.assertEqual(self.getJobFromHistory('project-merge').result,
1465 'SUCCESS')
1466 self.assertEqual(self.getJobFromHistory('project-test1').result,
1467 'SUCCESS')
1468 self.assertEqual(self.getJobFromHistory('project-test2').result,
1469 'SUCCESS')
1470 self.assertEqual(A.data['status'], 'MERGED')
1471 self.assertEqual(A.reported, 2)
James E. Blairf62d4282012-12-31 17:01:50 -08001472
1473 def test_single_nonexistent_post_job(self):
1474 "Test launching a single post job that doesn't exist"
James E. Blairf62d4282012-12-31 17:01:50 -08001475 e = {
1476 "type": "ref-updated",
1477 "submitter": {
1478 "name": "User Name",
1479 },
1480 "refUpdate": {
1481 "oldRev": "90f173846e3af9154517b88543ffbd1691f31366",
1482 "newRev": "d479a0bfcb34da57a31adb2a595c0cf687812543",
1483 "refName": "master",
1484 "project": "org/project",
1485 }
1486 }
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001487 # Set to the state immediately after a restart
1488 self.resetGearmanServer()
1489 self.launcher.negative_function_cache_ttl = 0
1490
James E. Blairf62d4282012-12-31 17:01:50 -08001491 self.fake_gerrit.addEvent(e)
1492 self.waitUntilSettled()
1493
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001494 self.assertEqual(len(self.history), 0)
James E. Blair2fa50962013-01-30 21:50:41 -08001495
1496 def test_new_patchset_dequeues_old(self):
1497 "Test that a new patchset causes the old to be dequeued"
1498 # D -> C (depends on B) -> B (depends on A) -> A -> M
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001499 self.worker.hold_jobs_in_build = True
James E. Blair2fa50962013-01-30 21:50:41 -08001500 M = self.fake_gerrit.addFakeChange('org/project', 'master', 'M')
1501 M.setMerged()
1502
1503 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1504 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1505 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1506 D = self.fake_gerrit.addFakeChange('org/project', 'master', 'D')
1507 A.addApproval('CRVW', 2)
1508 B.addApproval('CRVW', 2)
1509 C.addApproval('CRVW', 2)
1510 D.addApproval('CRVW', 2)
1511
1512 C.setDependsOn(B, 1)
1513 B.setDependsOn(A, 1)
1514 A.setDependsOn(M, 1)
1515
1516 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1517 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1518 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1519 self.fake_gerrit.addEvent(D.addApproval('APRV', 1))
1520 self.waitUntilSettled()
1521
1522 B.addPatchset()
1523 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(2))
1524 self.waitUntilSettled()
1525
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001526 self.worker.hold_jobs_in_build = False
1527 self.worker.release()
James E. Blair2fa50962013-01-30 21:50:41 -08001528 self.waitUntilSettled()
1529
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001530 self.assertEqual(A.data['status'], 'MERGED')
1531 self.assertEqual(A.reported, 2)
1532 self.assertEqual(B.data['status'], 'NEW')
1533 self.assertEqual(B.reported, 2)
1534 self.assertEqual(C.data['status'], 'NEW')
1535 self.assertEqual(C.reported, 2)
1536 self.assertEqual(D.data['status'], 'MERGED')
1537 self.assertEqual(D.reported, 2)
1538 self.assertEqual(len(self.history), 9) # 3 each for A, B, D.
James E. Blair2fa50962013-01-30 21:50:41 -08001539
James E. Blairba437362015-02-07 11:41:52 -08001540 def test_new_patchset_check(self):
1541 "Test a new patchset in check"
Antoine Mussobd86a312014-01-08 14:51:33 +01001542
1543 self.worker.hold_jobs_in_build = True
1544
1545 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
James E. Blairba437362015-02-07 11:41:52 -08001546 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1547 check_pipeline = self.sched.layout.pipelines['check']
1548
1549 # Add two git-dependent changes
1550 B.setDependsOn(A, 1)
1551 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1552 self.waitUntilSettled()
Antoine Mussobd86a312014-01-08 14:51:33 +01001553 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1554 self.waitUntilSettled()
James E. Blairba437362015-02-07 11:41:52 -08001555
1556 # A live item, and a non-live/live pair
1557 items = check_pipeline.getAllItems()
1558 self.assertEqual(len(items), 3)
1559
1560 self.assertEqual(items[0].change.number, '1')
1561 self.assertEqual(items[0].change.patchset, '1')
1562 self.assertFalse(items[0].live)
1563
1564 self.assertEqual(items[1].change.number, '2')
1565 self.assertEqual(items[1].change.patchset, '1')
1566 self.assertTrue(items[1].live)
1567
1568 self.assertEqual(items[2].change.number, '1')
1569 self.assertEqual(items[2].change.patchset, '1')
1570 self.assertTrue(items[2].live)
1571
1572 # Add a new patchset to A
1573 A.addPatchset()
1574 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
1575 self.waitUntilSettled()
1576
1577 # The live copy of A,1 should be gone, but the non-live and B
1578 # should continue, and we should have a new A,2
1579 items = check_pipeline.getAllItems()
1580 self.assertEqual(len(items), 3)
1581
1582 self.assertEqual(items[0].change.number, '1')
1583 self.assertEqual(items[0].change.patchset, '1')
1584 self.assertFalse(items[0].live)
1585
1586 self.assertEqual(items[1].change.number, '2')
1587 self.assertEqual(items[1].change.patchset, '1')
1588 self.assertTrue(items[1].live)
1589
1590 self.assertEqual(items[2].change.number, '1')
1591 self.assertEqual(items[2].change.patchset, '2')
1592 self.assertTrue(items[2].live)
1593
1594 # Add a new patchset to B
1595 B.addPatchset()
1596 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(2))
1597 self.waitUntilSettled()
1598
1599 # The live copy of B,1 should be gone, and it's non-live copy of A,1
1600 # but we should have a new B,2 (still based on A,1)
1601 items = check_pipeline.getAllItems()
1602 self.assertEqual(len(items), 3)
1603
1604 self.assertEqual(items[0].change.number, '1')
1605 self.assertEqual(items[0].change.patchset, '2')
1606 self.assertTrue(items[0].live)
1607
1608 self.assertEqual(items[1].change.number, '1')
1609 self.assertEqual(items[1].change.patchset, '1')
1610 self.assertFalse(items[1].live)
1611
1612 self.assertEqual(items[2].change.number, '2')
1613 self.assertEqual(items[2].change.patchset, '2')
1614 self.assertTrue(items[2].live)
1615
1616 self.builds[0].release()
1617 self.waitUntilSettled()
1618 self.builds[0].release()
1619 self.waitUntilSettled()
1620 self.worker.hold_jobs_in_build = False
1621 self.worker.release()
1622 self.waitUntilSettled()
1623
1624 self.assertEqual(A.reported, 1)
1625 self.assertEqual(B.reported, 1)
1626 self.assertEqual(self.history[0].result, 'ABORTED')
1627 self.assertEqual(self.history[0].changes, '1,1')
1628 self.assertEqual(self.history[1].result, 'ABORTED')
1629 self.assertEqual(self.history[1].changes, '1,1 2,1')
1630 self.assertEqual(self.history[2].result, 'SUCCESS')
1631 self.assertEqual(self.history[2].changes, '1,2')
1632 self.assertEqual(self.history[3].result, 'SUCCESS')
1633 self.assertEqual(self.history[3].changes, '1,1 2,2')
1634
1635 def test_abandoned_gate(self):
1636 "Test that an abandoned change is dequeued from gate"
1637
1638 self.worker.hold_jobs_in_build = True
1639
1640 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1641 A.addApproval('CRVW', 2)
1642 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1643 self.waitUntilSettled()
Antoine Mussobd86a312014-01-08 14:51:33 +01001644 self.assertEqual(len(self.builds), 1, "One job being built (on hold)")
1645 self.assertEqual(self.builds[0].name, 'project-merge')
1646
1647 self.fake_gerrit.addEvent(A.getChangeAbandonedEvent())
1648 self.waitUntilSettled()
1649
Antoine Mussobd86a312014-01-08 14:51:33 +01001650 self.worker.release('.*-merge')
1651 self.waitUntilSettled()
1652
1653 self.assertEqual(len(self.builds), 0, "No job running")
Antoine Mussobd86a312014-01-08 14:51:33 +01001654 self.assertEqual(len(self.history), 1, "Only one build in history")
1655 self.assertEqual(self.history[0].result, 'ABORTED',
James E. Blairba437362015-02-07 11:41:52 -08001656 "Build should have been aborted")
1657 self.assertEqual(A.reported, 1,
1658 "Abandoned gate change should report only start")
1659
1660 def test_abandoned_check(self):
1661 "Test that an abandoned change is dequeued from check"
1662
1663 self.worker.hold_jobs_in_build = True
1664
1665 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1666 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1667 check_pipeline = self.sched.layout.pipelines['check']
1668
1669 # Add two git-dependent changes
1670 B.setDependsOn(A, 1)
1671 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1672 self.waitUntilSettled()
1673 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1674 self.waitUntilSettled()
1675 # A live item, and a non-live/live pair
1676 items = check_pipeline.getAllItems()
1677 self.assertEqual(len(items), 3)
1678
1679 self.assertEqual(items[0].change.number, '1')
1680 self.assertFalse(items[0].live)
1681
1682 self.assertEqual(items[1].change.number, '2')
1683 self.assertTrue(items[1].live)
1684
1685 self.assertEqual(items[2].change.number, '1')
1686 self.assertTrue(items[2].live)
1687
1688 # Abandon A
1689 self.fake_gerrit.addEvent(A.getChangeAbandonedEvent())
1690 self.waitUntilSettled()
1691
1692 # The live copy of A should be gone, but the non-live and B
1693 # should continue
1694 items = check_pipeline.getAllItems()
1695 self.assertEqual(len(items), 2)
1696
1697 self.assertEqual(items[0].change.number, '1')
1698 self.assertFalse(items[0].live)
1699
1700 self.assertEqual(items[1].change.number, '2')
1701 self.assertTrue(items[1].live)
1702
1703 self.worker.hold_jobs_in_build = False
1704 self.worker.release()
1705 self.waitUntilSettled()
1706
1707 self.assertEqual(len(self.history), 4)
1708 self.assertEqual(self.history[0].result, 'ABORTED',
Antoine Mussobd86a312014-01-08 14:51:33 +01001709 'Build should have been aborted')
1710 self.assertEqual(A.reported, 0, "Abandoned change should not report")
James E. Blairba437362015-02-07 11:41:52 -08001711 self.assertEqual(B.reported, 1, "Change should report")
Antoine Mussobd86a312014-01-08 14:51:33 +01001712
Steve Varnau7b78b312015-04-03 14:49:46 -07001713 def test_abandoned_not_timer(self):
1714 "Test that an abandoned change does not cancel timer jobs"
1715
1716 self.worker.hold_jobs_in_build = True
1717
1718 # Start timer trigger - also org/project
1719 self.config.set('zuul', 'layout_config',
1720 'tests/fixtures/layout-idle.yaml')
1721 self.sched.reconfigure(self.config)
1722 self.registerJobs()
1723 # The pipeline triggers every second, so we should have seen
1724 # several by now.
1725 time.sleep(5)
1726 self.waitUntilSettled()
1727 # Stop queuing timer triggered jobs so that the assertions
1728 # below don't race against more jobs being queued.
1729 self.config.set('zuul', 'layout_config',
1730 'tests/fixtures/layout-no-timer.yaml')
1731 self.sched.reconfigure(self.config)
1732 self.registerJobs()
1733 self.assertEqual(len(self.builds), 2, "Two timer jobs")
1734
1735 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1736 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1737 self.waitUntilSettled()
1738 self.assertEqual(len(self.builds), 3, "One change plus two timer jobs")
1739
1740 self.fake_gerrit.addEvent(A.getChangeAbandonedEvent())
1741 self.waitUntilSettled()
1742
1743 self.assertEqual(len(self.builds), 2, "Two timer jobs remain")
1744
1745 self.worker.release()
1746 self.waitUntilSettled()
1747
Arx Cruzb1b010d2013-10-28 19:49:59 -02001748 def test_zuul_url_return(self):
1749 "Test if ZUUL_URL is returning when zuul_url is set in zuul.conf"
James E. Blair4076e2b2014-01-28 12:42:20 -08001750 self.assertTrue(self.sched.config.has_option('merger', 'zuul_url'))
Arx Cruzb1b010d2013-10-28 19:49:59 -02001751 self.worker.hold_jobs_in_build = True
1752
1753 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1754 A.addApproval('CRVW', 2)
1755 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1756 self.waitUntilSettled()
1757
1758 self.assertEqual(len(self.builds), 1)
1759 for build in self.builds:
1760 self.assertTrue('ZUUL_URL' in build.parameters)
1761
1762 self.worker.hold_jobs_in_build = False
1763 self.worker.release()
1764 self.waitUntilSettled()
1765
James E. Blair2fa50962013-01-30 21:50:41 -08001766 def test_new_patchset_dequeues_old_on_head(self):
1767 "Test that a new patchset causes the old to be dequeued (at head)"
1768 # D -> C (depends on B) -> B (depends on A) -> A -> M
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001769 self.worker.hold_jobs_in_build = True
James E. Blair2fa50962013-01-30 21:50:41 -08001770 M = self.fake_gerrit.addFakeChange('org/project', 'master', 'M')
1771 M.setMerged()
1772 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1773 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1774 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1775 D = self.fake_gerrit.addFakeChange('org/project', 'master', 'D')
1776 A.addApproval('CRVW', 2)
1777 B.addApproval('CRVW', 2)
1778 C.addApproval('CRVW', 2)
1779 D.addApproval('CRVW', 2)
1780
1781 C.setDependsOn(B, 1)
1782 B.setDependsOn(A, 1)
1783 A.setDependsOn(M, 1)
1784
1785 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1786 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1787 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1788 self.fake_gerrit.addEvent(D.addApproval('APRV', 1))
1789 self.waitUntilSettled()
1790
1791 A.addPatchset()
1792 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
1793 self.waitUntilSettled()
1794
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001795 self.worker.hold_jobs_in_build = False
1796 self.worker.release()
James E. Blair2fa50962013-01-30 21:50:41 -08001797 self.waitUntilSettled()
1798
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001799 self.assertEqual(A.data['status'], 'NEW')
1800 self.assertEqual(A.reported, 2)
1801 self.assertEqual(B.data['status'], 'NEW')
1802 self.assertEqual(B.reported, 2)
1803 self.assertEqual(C.data['status'], 'NEW')
1804 self.assertEqual(C.reported, 2)
1805 self.assertEqual(D.data['status'], 'MERGED')
1806 self.assertEqual(D.reported, 2)
1807 self.assertEqual(len(self.history), 7)
James E. Blair2fa50962013-01-30 21:50:41 -08001808
1809 def test_new_patchset_dequeues_old_without_dependents(self):
1810 "Test that a new patchset causes only the old to be dequeued"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001811 self.worker.hold_jobs_in_build = True
James E. Blair2fa50962013-01-30 21:50:41 -08001812 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1813 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1814 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1815 A.addApproval('CRVW', 2)
1816 B.addApproval('CRVW', 2)
1817 C.addApproval('CRVW', 2)
1818
1819 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1820 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1821 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1822 self.waitUntilSettled()
1823
1824 B.addPatchset()
1825 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(2))
1826 self.waitUntilSettled()
1827
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001828 self.worker.hold_jobs_in_build = False
1829 self.worker.release()
James E. Blair2fa50962013-01-30 21:50:41 -08001830 self.waitUntilSettled()
1831
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001832 self.assertEqual(A.data['status'], 'MERGED')
1833 self.assertEqual(A.reported, 2)
1834 self.assertEqual(B.data['status'], 'NEW')
1835 self.assertEqual(B.reported, 2)
1836 self.assertEqual(C.data['status'], 'MERGED')
1837 self.assertEqual(C.reported, 2)
1838 self.assertEqual(len(self.history), 9)
James E. Blair2fa50962013-01-30 21:50:41 -08001839
1840 def test_new_patchset_dequeues_old_independent_queue(self):
1841 "Test that a new patchset causes the old to be dequeued (independent)"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001842 self.worker.hold_jobs_in_build = True
James E. Blair2fa50962013-01-30 21:50:41 -08001843 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1844 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1845 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1846 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1847 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1848 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
1849 self.waitUntilSettled()
1850
1851 B.addPatchset()
1852 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(2))
1853 self.waitUntilSettled()
1854
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001855 self.worker.hold_jobs_in_build = False
1856 self.worker.release()
James E. Blair2fa50962013-01-30 21:50:41 -08001857 self.waitUntilSettled()
1858
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001859 self.assertEqual(A.data['status'], 'NEW')
1860 self.assertEqual(A.reported, 1)
1861 self.assertEqual(B.data['status'], 'NEW')
1862 self.assertEqual(B.reported, 1)
1863 self.assertEqual(C.data['status'], 'NEW')
1864 self.assertEqual(C.reported, 1)
1865 self.assertEqual(len(self.history), 10)
1866 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 1)
James E. Blair7d0dedc2013-02-21 17:26:09 -08001867
James E. Blair18c64442014-03-18 10:14:45 -07001868 def test_noop_job(self):
1869 "Test that the internal noop job works"
1870 A = self.fake_gerrit.addFakeChange('org/noop-project', 'master', 'A')
1871 A.addApproval('CRVW', 2)
1872 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1873 self.waitUntilSettled()
1874
1875 self.assertEqual(len(self.gearman_server.getQueue()), 0)
1876 self.assertTrue(self.sched._areAllBuildsComplete())
1877 self.assertEqual(len(self.history), 0)
1878 self.assertEqual(A.data['status'], 'MERGED')
1879 self.assertEqual(A.reported, 2)
1880
Evgeny Antyshevd6e546c2015-06-11 15:13:57 +00001881 def test_no_job_project(self):
1882 "Test that reports with no jobs don't get sent"
1883 A = self.fake_gerrit.addFakeChange('org/no-jobs-project',
1884 'master', 'A')
1885 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1886 self.waitUntilSettled()
1887
1888 # Change wasn't reported to
1889 self.assertEqual(A.reported, False)
1890
1891 # Check queue is empty afterwards
1892 check_pipeline = self.sched.layout.pipelines['check']
1893 items = check_pipeline.getAllItems()
1894 self.assertEqual(len(items), 0)
1895
1896 self.assertEqual(len(self.history), 0)
1897
James E. Blair7d0dedc2013-02-21 17:26:09 -08001898 def test_zuul_refs(self):
1899 "Test that zuul refs exist and have the right changes"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001900 self.worker.hold_jobs_in_build = True
James E. Blair7d0dedc2013-02-21 17:26:09 -08001901 M1 = self.fake_gerrit.addFakeChange('org/project1', 'master', 'M1')
1902 M1.setMerged()
1903 M2 = self.fake_gerrit.addFakeChange('org/project2', 'master', 'M2')
1904 M2.setMerged()
1905
1906 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
1907 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
1908 C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
1909 D = self.fake_gerrit.addFakeChange('org/project2', 'master', 'D')
1910 A.addApproval('CRVW', 2)
1911 B.addApproval('CRVW', 2)
1912 C.addApproval('CRVW', 2)
1913 D.addApproval('CRVW', 2)
1914 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1915 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1916 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1917 self.fake_gerrit.addEvent(D.addApproval('APRV', 1))
1918
1919 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001920 self.worker.release('.*-merge')
James E. Blair7d0dedc2013-02-21 17:26:09 -08001921 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001922 self.worker.release('.*-merge')
James E. Blair7d0dedc2013-02-21 17:26:09 -08001923 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001924 self.worker.release('.*-merge')
James E. Blair7d0dedc2013-02-21 17:26:09 -08001925 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001926 self.worker.release('.*-merge')
James E. Blair7d0dedc2013-02-21 17:26:09 -08001927 self.waitUntilSettled()
1928
James E. Blair7d0dedc2013-02-21 17:26:09 -08001929 a_zref = b_zref = c_zref = d_zref = None
Monty Taylor6bef8ef2013-06-02 08:17:12 -04001930 for x in self.builds:
James E. Blair7d0dedc2013-02-21 17:26:09 -08001931 if x.parameters['ZUUL_CHANGE'] == '3':
1932 a_zref = x.parameters['ZUUL_REF']
1933 if x.parameters['ZUUL_CHANGE'] == '4':
1934 b_zref = x.parameters['ZUUL_REF']
1935 if x.parameters['ZUUL_CHANGE'] == '5':
1936 c_zref = x.parameters['ZUUL_REF']
1937 if x.parameters['ZUUL_CHANGE'] == '6':
1938 d_zref = x.parameters['ZUUL_REF']
1939
1940 # There are... four... refs.
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001941 self.assertIsNotNone(a_zref)
1942 self.assertIsNotNone(b_zref)
1943 self.assertIsNotNone(c_zref)
1944 self.assertIsNotNone(d_zref)
James E. Blair7d0dedc2013-02-21 17:26:09 -08001945
1946 # And they should all be different
1947 refs = set([a_zref, b_zref, c_zref, d_zref])
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001948 self.assertEqual(len(refs), 4)
James E. Blair7d0dedc2013-02-21 17:26:09 -08001949
1950 # a ref should have a, not b, and should not be in project2
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001951 self.assertTrue(self.ref_has_change(a_zref, A))
1952 self.assertFalse(self.ref_has_change(a_zref, B))
1953 self.assertFalse(self.ref_has_change(a_zref, M2))
James E. Blair7d0dedc2013-02-21 17:26:09 -08001954
1955 # b ref should have a and b, and should not be in project2
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001956 self.assertTrue(self.ref_has_change(b_zref, A))
1957 self.assertTrue(self.ref_has_change(b_zref, B))
1958 self.assertFalse(self.ref_has_change(b_zref, M2))
James E. Blair7d0dedc2013-02-21 17:26:09 -08001959
1960 # c ref should have a and b in 1, c in 2
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001961 self.assertTrue(self.ref_has_change(c_zref, A))
1962 self.assertTrue(self.ref_has_change(c_zref, B))
1963 self.assertTrue(self.ref_has_change(c_zref, C))
1964 self.assertFalse(self.ref_has_change(c_zref, D))
James E. Blair7d0dedc2013-02-21 17:26:09 -08001965
1966 # d ref should have a and b in 1, c and d in 2
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001967 self.assertTrue(self.ref_has_change(d_zref, A))
1968 self.assertTrue(self.ref_has_change(d_zref, B))
1969 self.assertTrue(self.ref_has_change(d_zref, C))
1970 self.assertTrue(self.ref_has_change(d_zref, D))
James E. Blair7d0dedc2013-02-21 17:26:09 -08001971
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001972 self.worker.hold_jobs_in_build = False
1973 self.worker.release()
James E. Blair7d0dedc2013-02-21 17:26:09 -08001974 self.waitUntilSettled()
1975
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001976 self.assertEqual(A.data['status'], 'MERGED')
1977 self.assertEqual(A.reported, 2)
1978 self.assertEqual(B.data['status'], 'MERGED')
1979 self.assertEqual(B.reported, 2)
1980 self.assertEqual(C.data['status'], 'MERGED')
1981 self.assertEqual(C.reported, 2)
1982 self.assertEqual(D.data['status'], 'MERGED')
1983 self.assertEqual(D.reported, 2)
James E. Blair70c71582013-03-06 08:50:50 -08001984
James E. Blair4a28a882013-08-23 15:17:33 -07001985 def test_rerun_on_error(self):
1986 "Test that if a worker fails to run a job, it is run again"
1987 self.worker.hold_jobs_in_build = True
1988 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1989 A.addApproval('CRVW', 2)
1990 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1991 self.waitUntilSettled()
1992
1993 self.builds[0].run_error = True
1994 self.worker.hold_jobs_in_build = False
1995 self.worker.release()
1996 self.waitUntilSettled()
1997 self.assertEqual(self.countJobResults(self.history, 'RUN_ERROR'), 1)
1998 self.assertEqual(self.countJobResults(self.history, 'SUCCESS'), 3)
1999
James E. Blair412e5582013-04-22 15:50:12 -07002000 def test_statsd(self):
2001 "Test each of the statsd methods used in the scheduler"
2002 import extras
2003 statsd = extras.try_import('statsd.statsd')
2004 statsd.incr('test-incr')
2005 statsd.timing('test-timing', 3)
Alex Gaynor813d39b2014-05-17 16:17:16 -07002006 statsd.gauge('test-gauge', 12)
James E. Blair412e5582013-04-22 15:50:12 -07002007 self.assertReportedStat('test-incr', '1|c')
2008 self.assertReportedStat('test-timing', '3|ms')
Alex Gaynor813d39b2014-05-17 16:17:16 -07002009 self.assertReportedStat('test-gauge', '12|g')
James E. Blair412e5582013-04-22 15:50:12 -07002010
James E. Blairdad52252014-02-07 16:59:17 -08002011 def test_stuck_job_cleanup(self):
2012 "Test that pending jobs are cleaned up if removed from layout"
James E. Blair18c64442014-03-18 10:14:45 -07002013 # This job won't be registered at startup because it is not in
2014 # the standard layout, but we need it to already be registerd
2015 # for when we reconfigure, as that is when Zuul will attempt
2016 # to run the new job.
2017 self.worker.registerFunction('build:gate-noop')
James E. Blairdad52252014-02-07 16:59:17 -08002018 self.gearman_server.hold_jobs_in_queue = True
2019 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2020 A.addApproval('CRVW', 2)
2021 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2022 self.waitUntilSettled()
2023 self.assertEqual(len(self.gearman_server.getQueue()), 1)
2024
2025 self.config.set('zuul', 'layout_config',
2026 'tests/fixtures/layout-no-jobs.yaml')
2027 self.sched.reconfigure(self.config)
2028 self.waitUntilSettled()
2029
James E. Blair18c64442014-03-18 10:14:45 -07002030 self.gearman_server.release('gate-noop')
James E. Blairdad52252014-02-07 16:59:17 -08002031 self.waitUntilSettled()
2032 self.assertEqual(len(self.gearman_server.getQueue()), 0)
2033 self.assertTrue(self.sched._areAllBuildsComplete())
2034
2035 self.assertEqual(len(self.history), 1)
James E. Blair18c64442014-03-18 10:14:45 -07002036 self.assertEqual(self.history[0].name, 'gate-noop')
James E. Blairdad52252014-02-07 16:59:17 -08002037 self.assertEqual(self.history[0].result, 'SUCCESS')
2038
James E. Blair879dafb2015-07-17 14:04:49 -07002039 def test_file_head(self):
2040 # This is a regression test for an observed bug. A change
2041 # with a file named "HEAD" in the root directory of the repo
2042 # was processed by a merger. It then was unable to reset the
2043 # repo because of:
2044 # GitCommandError: 'git reset --hard HEAD' returned
2045 # with exit code 128
2046 # stderr: 'fatal: ambiguous argument 'HEAD': both revision
2047 # and filename
2048 # Use '--' to separate filenames from revisions'
2049
2050 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2051 A.addPatchset(['HEAD'])
2052 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2053
2054 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
2055 self.waitUntilSettled()
2056
2057 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2058 self.waitUntilSettled()
2059
2060 self.assertIn('Build succeeded', A.messages[0])
2061 self.assertIn('Build succeeded', B.messages[0])
2062
James E. Blair70c71582013-03-06 08:50:50 -08002063 def test_file_jobs(self):
2064 "Test that file jobs run only when appropriate"
2065 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2066 A.addPatchset(['pip-requires'])
2067 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2068 A.addApproval('CRVW', 2)
2069 B.addApproval('CRVW', 2)
2070 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2071 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2072 self.waitUntilSettled()
2073
Monty Taylor6bef8ef2013-06-02 08:17:12 -04002074 testfile_jobs = [x for x in self.history
James E. Blair70c71582013-03-06 08:50:50 -08002075 if x.name == 'project-testfile']
2076
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002077 self.assertEqual(len(testfile_jobs), 1)
2078 self.assertEqual(testfile_jobs[0].changes, '1,2')
2079 self.assertEqual(A.data['status'], 'MERGED')
2080 self.assertEqual(A.reported, 2)
2081 self.assertEqual(B.data['status'], 'MERGED')
2082 self.assertEqual(B.reported, 2)
James E. Blair3c5e5b52013-04-26 11:17:03 -07002083
Maru Newby3fe5f852015-01-13 04:22:14 +00002084 def _test_skip_if_jobs(self, branch, should_skip):
2085 "Test that jobs with a skip-if filter run only when appropriate"
2086 self.config.set('zuul', 'layout_config',
2087 'tests/fixtures/layout-skip-if.yaml')
2088 self.sched.reconfigure(self.config)
2089 self.registerJobs()
2090
2091 change = self.fake_gerrit.addFakeChange('org/project',
2092 branch,
2093 'test skip-if')
2094 self.fake_gerrit.addEvent(change.getPatchsetCreatedEvent(1))
2095 self.waitUntilSettled()
2096
2097 tested_change_ids = [x.changes[0] for x in self.history
2098 if x.name == 'project-test-skip-if']
2099
2100 if should_skip:
2101 self.assertEqual([], tested_change_ids)
2102 else:
2103 self.assertIn(change.data['number'], tested_change_ids)
2104
2105 def test_skip_if_match_skips_job(self):
2106 self._test_skip_if_jobs(branch='master', should_skip=True)
2107
2108 def test_skip_if_no_match_runs_job(self):
2109 self._test_skip_if_jobs(branch='mp', should_skip=False)
2110
James E. Blair3c5e5b52013-04-26 11:17:03 -07002111 def test_test_config(self):
2112 "Test that we can test the config"
2113 sched = zuul.scheduler.Scheduler()
James E. Blair6c358e72013-07-29 17:06:47 -07002114 sched.registerTrigger(None, 'gerrit')
James E. Blair63bb0ef2013-07-29 17:14:51 -07002115 sched.registerTrigger(None, 'timer')
James E. Blairc494d542014-08-06 09:23:52 -07002116 sched.registerTrigger(None, 'zuul')
Clark Boylanb640e052014-04-03 16:41:46 -07002117 sched.testConfig(self.config.get('zuul', 'layout_config'))
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002118
2119 def test_build_description(self):
2120 "Test that build descriptions update"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002121 self.worker.registerFunction('set_description:' +
2122 self.worker.worker_id)
2123
2124 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2125 A.addApproval('CRVW', 2)
2126 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2127 self.waitUntilSettled()
Monty Taylor6bef8ef2013-06-02 08:17:12 -04002128 desc = self.history[0].description
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002129 self.log.debug("Description: %s" % desc)
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002130 self.assertTrue(re.search("Branch.*master", desc))
2131 self.assertTrue(re.search("Pipeline.*gate", desc))
2132 self.assertTrue(re.search("project-merge.*SUCCESS", desc))
2133 self.assertTrue(re.search("project-test1.*SUCCESS", desc))
2134 self.assertTrue(re.search("project-test2.*SUCCESS", desc))
2135 self.assertTrue(re.search("Reported result.*SUCCESS", desc))
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002136
James E. Blairc8a1e052014-02-25 09:29:26 -08002137 def test_queue_names(self):
2138 "Test shared change queue names"
2139 project1 = self.sched.layout.projects['org/project1']
2140 project2 = self.sched.layout.projects['org/project2']
2141 q1 = self.sched.layout.pipelines['gate'].getQueue(project1)
2142 q2 = self.sched.layout.pipelines['gate'].getQueue(project2)
2143 self.assertEqual(q1.name, 'integration')
2144 self.assertEqual(q2.name, 'integration')
2145
2146 self.config.set('zuul', 'layout_config',
2147 'tests/fixtures/layout-bad-queue.yaml')
2148 with testtools.ExpectedException(
2149 Exception, "More than one name assigned to change queue"):
2150 self.sched.reconfigure(self.config)
2151
James E. Blair64ed6f22013-07-10 14:07:23 -07002152 def test_queue_precedence(self):
2153 "Test that queue precedence works"
2154
2155 self.gearman_server.hold_jobs_in_queue = True
James E. Blair8de58bd2013-07-18 16:23:33 -07002156 self.worker.hold_jobs_in_build = True
James E. Blair64ed6f22013-07-10 14:07:23 -07002157 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2158 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2159 A.addApproval('CRVW', 2)
2160 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2161
2162 self.waitUntilSettled()
2163 self.gearman_server.hold_jobs_in_queue = False
2164 self.gearman_server.release()
2165 self.waitUntilSettled()
2166
James E. Blair8de58bd2013-07-18 16:23:33 -07002167 # Run one build at a time to ensure non-race order:
James E. Blairb8c16472015-05-05 14:55:26 -07002168 self.orderedRelease()
James E. Blair8de58bd2013-07-18 16:23:33 -07002169 self.worker.hold_jobs_in_build = False
2170 self.waitUntilSettled()
2171
James E. Blair64ed6f22013-07-10 14:07:23 -07002172 self.log.debug(self.history)
2173 self.assertEqual(self.history[0].pipeline, 'gate')
2174 self.assertEqual(self.history[1].pipeline, 'check')
2175 self.assertEqual(self.history[2].pipeline, 'gate')
2176 self.assertEqual(self.history[3].pipeline, 'gate')
2177 self.assertEqual(self.history[4].pipeline, 'check')
2178 self.assertEqual(self.history[5].pipeline, 'check')
2179
Clark Boylana5edbe42014-06-03 16:39:10 -07002180 def test_json_status(self):
James E. Blair1843a552013-07-03 14:19:52 -07002181 "Test that we can retrieve JSON status info"
2182 self.worker.hold_jobs_in_build = True
2183 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2184 A.addApproval('CRVW', 2)
2185 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2186 self.waitUntilSettled()
2187
2188 port = self.webapp.server.socket.getsockname()[1]
2189
Yuriy Taradaya6d452f2014-04-16 12:36:20 +04002190 req = urllib2.Request("http://localhost:%s/status.json" % port)
Yuriy Taradaya6d452f2014-04-16 12:36:20 +04002191 f = urllib2.urlopen(req)
Clark Boylanaa4f2e72014-06-03 21:22:40 -07002192 headers = f.info()
2193 self.assertIn('Content-Length', headers)
2194 self.assertIn('Content-Type', headers)
2195 self.assertEqual(headers['Content-Type'],
2196 'application/json; charset=UTF-8')
Timo Tijhof0ebd2932015-04-02 12:11:21 +01002197 self.assertIn('Access-Control-Allow-Origin', headers)
2198 self.assertIn('Cache-Control', headers)
Clark Boylanaa4f2e72014-06-03 21:22:40 -07002199 self.assertIn('Last-Modified', headers)
Timo Tijhof0ebd2932015-04-02 12:11:21 +01002200 self.assertIn('Expires', headers)
James E. Blair1843a552013-07-03 14:19:52 -07002201 data = f.read()
2202
2203 self.worker.hold_jobs_in_build = False
2204 self.worker.release()
2205 self.waitUntilSettled()
2206
2207 data = json.loads(data)
2208 status_jobs = set()
2209 for p in data['pipelines']:
2210 for q in p['change_queues']:
James E. Blairbfb8e042014-12-30 17:01:44 -08002211 if p['name'] in ['gate', 'conflict']:
Clark Boylanaf2476f2014-01-23 14:47:36 -08002212 self.assertEqual(q['window'], 20)
2213 else:
2214 self.assertEqual(q['window'], 0)
James E. Blair1843a552013-07-03 14:19:52 -07002215 for head in q['heads']:
2216 for change in head:
Clark Boylanaf2476f2014-01-23 14:47:36 -08002217 self.assertTrue(change['active'])
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002218 self.assertEqual(change['id'], '1,1')
James E. Blair1843a552013-07-03 14:19:52 -07002219 for job in change['jobs']:
2220 status_jobs.add(job['name'])
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002221 self.assertIn('project-merge', status_jobs)
2222 self.assertIn('project-test1', status_jobs)
2223 self.assertIn('project-test2', status_jobs)
James E. Blair1843a552013-07-03 14:19:52 -07002224
James E. Blairc3d428e2013-12-03 15:06:48 -08002225 def test_merging_queues(self):
2226 "Test that transitively-connected change queues are merged"
2227 self.config.set('zuul', 'layout_config',
2228 'tests/fixtures/layout-merge-queues.yaml')
2229 self.sched.reconfigure(self.config)
2230 self.assertEqual(len(self.sched.layout.pipelines['gate'].queues), 1)
2231
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002232 def test_node_label(self):
2233 "Test that a job runs on a specific node label"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002234 self.worker.registerFunction('build:node-project-test1:debian')
2235
2236 A = self.fake_gerrit.addFakeChange('org/node-project', 'master', 'A')
2237 A.addApproval('CRVW', 2)
2238 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2239 self.waitUntilSettled()
James E. Blair4ca985f2013-05-30 12:27:43 -07002240
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002241 self.assertIsNone(self.getJobFromHistory('node-project-merge').node)
2242 self.assertEqual(self.getJobFromHistory('node-project-test1').node,
2243 'debian')
2244 self.assertIsNone(self.getJobFromHistory('node-project-test2').node)
James E. Blaircdccd972013-07-01 12:10:22 -07002245
2246 def test_live_reconfiguration(self):
2247 "Test that live reconfiguration works"
2248 self.worker.hold_jobs_in_build = True
2249 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2250 A.addApproval('CRVW', 2)
2251 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2252 self.waitUntilSettled()
2253
2254 self.sched.reconfigure(self.config)
2255
2256 self.worker.hold_jobs_in_build = False
2257 self.worker.release()
2258 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002259 self.assertEqual(self.getJobFromHistory('project-merge').result,
2260 'SUCCESS')
2261 self.assertEqual(self.getJobFromHistory('project-test1').result,
2262 'SUCCESS')
2263 self.assertEqual(self.getJobFromHistory('project-test2').result,
2264 'SUCCESS')
2265 self.assertEqual(A.data['status'], 'MERGED')
2266 self.assertEqual(A.reported, 2)
James E. Blair287c06d2013-07-24 10:39:30 -07002267
James E. Blair6bc782d2015-07-17 16:20:21 -07002268 def test_live_reconfiguration_merge_conflict(self):
2269 # A real-world bug: a change in a gate queue has a merge
2270 # conflict and a job is added to its project while it's
2271 # sitting in the queue. The job gets added to the change and
2272 # enqueued and the change gets stuck.
2273 self.worker.registerFunction('build:project-test3')
2274 self.worker.hold_jobs_in_build = True
2275
2276 # This change is fine. It's here to stop the queue long
2277 # enough for the next change to be subject to the
2278 # reconfiguration, as well as to provide a conflict for the
2279 # next change. This change will succeed and merge.
2280 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2281 A.addPatchset(['conflict'])
2282 A.addApproval('CRVW', 2)
James E. Blair6bc782d2015-07-17 16:20:21 -07002283
2284 # This change will be in merge conflict. During the
2285 # reconfiguration, we will add a job. We want to make sure
2286 # that doesn't cause it to get stuck.
2287 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2288 B.addPatchset(['conflict'])
2289 B.addApproval('CRVW', 2)
James E. Blair4eb21fa2015-07-27 14:56:47 -07002290
2291 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
James E. Blair6bc782d2015-07-17 16:20:21 -07002292 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2293
2294 self.waitUntilSettled()
2295
2296 # No jobs have run yet
2297 self.assertEqual(A.data['status'], 'NEW')
2298 self.assertEqual(A.reported, 1)
2299 self.assertEqual(B.data['status'], 'NEW')
2300 self.assertEqual(B.reported, 1)
2301 self.assertEqual(len(self.history), 0)
2302
2303 # Add the "project-test3" job.
2304 self.config.set('zuul', 'layout_config',
2305 'tests/fixtures/layout-live-'
2306 'reconfiguration-add-job.yaml')
2307 self.sched.reconfigure(self.config)
2308 self.waitUntilSettled()
2309
2310 self.worker.hold_jobs_in_build = False
2311 self.worker.release()
2312 self.waitUntilSettled()
2313
2314 self.assertEqual(A.data['status'], 'MERGED')
2315 self.assertEqual(A.reported, 2)
2316 self.assertEqual(B.data['status'], 'NEW')
2317 self.assertEqual(B.reported, 2)
2318 self.assertEqual(self.getJobFromHistory('project-merge').result,
2319 'SUCCESS')
2320 self.assertEqual(self.getJobFromHistory('project-test1').result,
2321 'SUCCESS')
2322 self.assertEqual(self.getJobFromHistory('project-test2').result,
2323 'SUCCESS')
2324 self.assertEqual(self.getJobFromHistory('project-test3').result,
2325 'SUCCESS')
2326 self.assertEqual(len(self.history), 4)
2327
James E. Blair400e8fd2015-07-30 17:44:45 -07002328 def test_live_reconfiguration_failed_root(self):
James E. Blair6bc782d2015-07-17 16:20:21 -07002329 # An extrapolation of test_live_reconfiguration_merge_conflict
2330 # that tests a job added to a job tree with a failed root does
2331 # not run.
2332 self.worker.registerFunction('build:project-test3')
2333 self.worker.hold_jobs_in_build = True
2334
2335 # This change is fine. It's here to stop the queue long
2336 # enough for the next change to be subject to the
2337 # reconfiguration. This change will succeed and merge.
2338 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2339 A.addPatchset(['conflict'])
2340 A.addApproval('CRVW', 2)
2341 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2342 self.waitUntilSettled()
2343 self.worker.release('.*-merge')
2344 self.waitUntilSettled()
2345
2346 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2347 self.worker.addFailTest('project-merge', B)
2348 B.addApproval('CRVW', 2)
2349 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2350 self.waitUntilSettled()
2351
2352 self.worker.release('.*-merge')
2353 self.waitUntilSettled()
2354
2355 # Both -merge jobs have run, but no others.
2356 self.assertEqual(A.data['status'], 'NEW')
2357 self.assertEqual(A.reported, 1)
2358 self.assertEqual(B.data['status'], 'NEW')
2359 self.assertEqual(B.reported, 1)
2360 self.assertEqual(self.history[0].result, 'SUCCESS')
2361 self.assertEqual(self.history[0].name, 'project-merge')
2362 self.assertEqual(self.history[1].result, 'FAILURE')
2363 self.assertEqual(self.history[1].name, 'project-merge')
2364 self.assertEqual(len(self.history), 2)
2365
2366 # Add the "project-test3" job.
2367 self.config.set('zuul', 'layout_config',
2368 'tests/fixtures/layout-live-'
2369 'reconfiguration-add-job.yaml')
2370 self.sched.reconfigure(self.config)
2371 self.waitUntilSettled()
2372
2373 self.worker.hold_jobs_in_build = False
2374 self.worker.release()
2375 self.waitUntilSettled()
2376
2377 self.assertEqual(A.data['status'], 'MERGED')
2378 self.assertEqual(A.reported, 2)
2379 self.assertEqual(B.data['status'], 'NEW')
2380 self.assertEqual(B.reported, 2)
2381 self.assertEqual(self.history[0].result, 'SUCCESS')
2382 self.assertEqual(self.history[0].name, 'project-merge')
2383 self.assertEqual(self.history[1].result, 'FAILURE')
2384 self.assertEqual(self.history[1].name, 'project-merge')
2385 self.assertEqual(self.history[2].result, 'SUCCESS')
2386 self.assertEqual(self.history[3].result, 'SUCCESS')
2387 self.assertEqual(self.history[4].result, 'SUCCESS')
2388 self.assertEqual(len(self.history), 5)
2389
James E. Blair400e8fd2015-07-30 17:44:45 -07002390 def test_live_reconfiguration_failed_job(self):
2391 # Test that a change with a removed failing job does not
2392 # disrupt reconfiguration. If a change has a failed job and
2393 # that job is removed during a reconfiguration, we observed a
2394 # bug where the code to re-set build statuses would run on
2395 # that build and raise an exception because the job no longer
2396 # existed.
2397 self.worker.hold_jobs_in_build = True
2398
2399 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2400
2401 # This change will fail and later be removed by the reconfiguration.
2402 self.worker.addFailTest('project-test1', A)
2403
2404 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2405 self.waitUntilSettled()
2406 self.worker.release('.*-merge')
2407 self.waitUntilSettled()
2408 self.worker.release('project-test1')
2409 self.waitUntilSettled()
2410
2411 self.assertEqual(A.data['status'], 'NEW')
2412 self.assertEqual(A.reported, 0)
2413
2414 self.assertEqual(self.getJobFromHistory('project-merge').result,
2415 'SUCCESS')
2416 self.assertEqual(self.getJobFromHistory('project-test1').result,
2417 'FAILURE')
2418 self.assertEqual(len(self.history), 2)
2419
2420 # Remove the test1 job.
2421 self.config.set('zuul', 'layout_config',
2422 'tests/fixtures/layout-live-'
2423 'reconfiguration-failed-job.yaml')
2424 self.sched.reconfigure(self.config)
2425 self.waitUntilSettled()
2426
2427 self.worker.hold_jobs_in_build = False
2428 self.worker.release()
2429 self.waitUntilSettled()
2430
2431 self.assertEqual(self.getJobFromHistory('project-test2').result,
2432 'SUCCESS')
2433 self.assertEqual(self.getJobFromHistory('project-testfile').result,
2434 'SUCCESS')
2435 self.assertEqual(len(self.history), 4)
2436
2437 self.assertEqual(A.data['status'], 'NEW')
2438 self.assertEqual(A.reported, 1)
2439 self.assertIn('Build succeeded', A.messages[0])
2440 # Ensure the removed job was not included in the report.
2441 self.assertNotIn('project-test1', A.messages[0])
2442
James E. Blairfe707d12015-08-05 15:18:15 -07002443 def test_live_reconfiguration_shared_queue(self):
2444 # Test that a change with a failing job which was removed from
2445 # this project but otherwise still exists in the system does
2446 # not disrupt reconfiguration.
2447
2448 self.worker.hold_jobs_in_build = True
2449
2450 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
2451
2452 self.worker.addFailTest('project1-project2-integration', A)
2453
2454 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2455 self.waitUntilSettled()
2456 self.worker.release('.*-merge')
2457 self.waitUntilSettled()
2458 self.worker.release('project1-project2-integration')
2459 self.waitUntilSettled()
2460
2461 self.assertEqual(A.data['status'], 'NEW')
2462 self.assertEqual(A.reported, 0)
2463
2464 self.assertEqual(self.getJobFromHistory('project1-merge').result,
2465 'SUCCESS')
2466 self.assertEqual(self.getJobFromHistory(
2467 'project1-project2-integration').result, 'FAILURE')
2468 self.assertEqual(len(self.history), 2)
2469
2470 # Remove the integration job.
2471 self.config.set('zuul', 'layout_config',
2472 'tests/fixtures/layout-live-'
2473 'reconfiguration-shared-queue.yaml')
2474 self.sched.reconfigure(self.config)
2475 self.waitUntilSettled()
2476
2477 self.worker.hold_jobs_in_build = False
2478 self.worker.release()
2479 self.waitUntilSettled()
2480
2481 self.assertEqual(self.getJobFromHistory('project1-merge').result,
2482 'SUCCESS')
2483 self.assertEqual(self.getJobFromHistory('project1-test1').result,
2484 'SUCCESS')
2485 self.assertEqual(self.getJobFromHistory('project1-test2').result,
2486 'SUCCESS')
2487 self.assertEqual(self.getJobFromHistory(
2488 'project1-project2-integration').result, 'FAILURE')
2489 self.assertEqual(len(self.history), 4)
2490
2491 self.assertEqual(A.data['status'], 'NEW')
2492 self.assertEqual(A.reported, 1)
2493 self.assertIn('Build succeeded', A.messages[0])
2494 # Ensure the removed job was not included in the report.
2495 self.assertNotIn('project1-project2-integration', A.messages[0])
2496
Evgeny Antyshev0deaaad2015-08-03 20:22:56 +00002497 def test_live_reconfiguration_del_project(self):
2498 # Test project deletion from layout
2499 # while changes are enqueued
2500
2501 self.worker.hold_jobs_in_build = True
2502 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2503 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
2504 C = self.fake_gerrit.addFakeChange('org/project1', 'master', 'C')
2505
2506 # A Depends-On: B
2507 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
2508 A.subject, B.data['id'])
2509 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2510
2511 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2512 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
2513 self.waitUntilSettled()
2514 self.worker.release('.*-merge')
2515 self.waitUntilSettled()
2516 self.assertEqual(len(self.builds), 5)
2517
2518 # This layout defines only org/project, not org/project1
2519 self.config.set('zuul', 'layout_config',
2520 'tests/fixtures/layout-live-'
2521 'reconfiguration-del-project.yaml')
2522 self.sched.reconfigure(self.config)
2523 self.waitUntilSettled()
2524
2525 # Builds for C aborted, builds for A succeed,
2526 # and have change B applied ahead
2527 job_c = self.getJobFromHistory('project1-test1')
2528 self.assertEqual(job_c.changes, '3,1')
2529 self.assertEqual(job_c.result, 'ABORTED')
2530
2531 self.worker.hold_jobs_in_build = False
2532 self.worker.release()
2533 self.waitUntilSettled()
2534
2535 self.assertEqual(self.getJobFromHistory('project-test1').changes,
2536 '2,1 1,1')
2537
2538 self.assertEqual(A.data['status'], 'NEW')
2539 self.assertEqual(B.data['status'], 'NEW')
2540 self.assertEqual(C.data['status'], 'NEW')
2541 self.assertEqual(A.reported, 1)
2542 self.assertEqual(B.reported, 0)
2543 self.assertEqual(C.reported, 0)
2544
2545 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 0)
2546 self.assertIn('Build succeeded', A.messages[0])
2547
James E. Blaire712d9f2013-07-31 11:40:11 -07002548 def test_live_reconfiguration_functions(self):
2549 "Test live reconfiguration with a custom function"
2550 self.worker.registerFunction('build:node-project-test1:debian')
2551 self.worker.registerFunction('build:node-project-test1:wheezy')
2552 A = self.fake_gerrit.addFakeChange('org/node-project', 'master', 'A')
2553 A.addApproval('CRVW', 2)
2554 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2555 self.waitUntilSettled()
2556
2557 self.assertIsNone(self.getJobFromHistory('node-project-merge').node)
2558 self.assertEqual(self.getJobFromHistory('node-project-test1').node,
2559 'debian')
2560 self.assertIsNone(self.getJobFromHistory('node-project-test2').node)
2561
2562 self.config.set('zuul', 'layout_config',
2563 'tests/fixtures/layout-live-'
2564 'reconfiguration-functions.yaml')
2565 self.sched.reconfigure(self.config)
2566 self.worker.build_history = []
2567
2568 B = self.fake_gerrit.addFakeChange('org/node-project', 'master', 'B')
2569 B.addApproval('CRVW', 2)
2570 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2571 self.waitUntilSettled()
2572
2573 self.assertIsNone(self.getJobFromHistory('node-project-merge').node)
2574 self.assertEqual(self.getJobFromHistory('node-project-test1').node,
2575 'wheezy')
2576 self.assertIsNone(self.getJobFromHistory('node-project-test2').node)
2577
James E. Blair287c06d2013-07-24 10:39:30 -07002578 def test_delayed_repo_init(self):
2579 self.config.set('zuul', 'layout_config',
2580 'tests/fixtures/layout-delayed-repo-init.yaml')
2581 self.sched.reconfigure(self.config)
2582
2583 self.init_repo("org/new-project")
2584 A = self.fake_gerrit.addFakeChange('org/new-project', 'master', 'A')
2585
2586 A.addApproval('CRVW', 2)
2587 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2588 self.waitUntilSettled()
2589 self.assertEqual(self.getJobFromHistory('project-merge').result,
2590 'SUCCESS')
2591 self.assertEqual(self.getJobFromHistory('project-test1').result,
2592 'SUCCESS')
2593 self.assertEqual(self.getJobFromHistory('project-test2').result,
2594 'SUCCESS')
2595 self.assertEqual(A.data['status'], 'MERGED')
2596 self.assertEqual(A.reported, 2)
James E. Blair63bb0ef2013-07-29 17:14:51 -07002597
Clark Boylan6dbbc482013-10-18 10:57:31 -07002598 def test_repo_deleted(self):
2599 self.config.set('zuul', 'layout_config',
2600 'tests/fixtures/layout-repo-deleted.yaml')
2601 self.sched.reconfigure(self.config)
2602
2603 self.init_repo("org/delete-project")
2604 A = self.fake_gerrit.addFakeChange('org/delete-project', 'master', 'A')
2605
2606 A.addApproval('CRVW', 2)
2607 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2608 self.waitUntilSettled()
2609 self.assertEqual(self.getJobFromHistory('project-merge').result,
2610 'SUCCESS')
2611 self.assertEqual(self.getJobFromHistory('project-test1').result,
2612 'SUCCESS')
2613 self.assertEqual(self.getJobFromHistory('project-test2').result,
2614 'SUCCESS')
2615 self.assertEqual(A.data['status'], 'MERGED')
2616 self.assertEqual(A.reported, 2)
2617
2618 # Delete org/new-project zuul repo. Should be recloned.
2619 shutil.rmtree(os.path.join(self.git_root, "org/delete-project"))
2620
2621 B = self.fake_gerrit.addFakeChange('org/delete-project', 'master', 'B')
2622
2623 B.addApproval('CRVW', 2)
2624 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2625 self.waitUntilSettled()
2626 self.assertEqual(self.getJobFromHistory('project-merge').result,
2627 'SUCCESS')
2628 self.assertEqual(self.getJobFromHistory('project-test1').result,
2629 'SUCCESS')
2630 self.assertEqual(self.getJobFromHistory('project-test2').result,
2631 'SUCCESS')
2632 self.assertEqual(B.data['status'], 'MERGED')
2633 self.assertEqual(B.reported, 2)
2634
James E. Blair63bb0ef2013-07-29 17:14:51 -07002635 def test_timer(self):
2636 "Test that a periodic job is triggered"
2637 self.worker.hold_jobs_in_build = True
2638 self.config.set('zuul', 'layout_config',
2639 'tests/fixtures/layout-timer.yaml')
2640 self.sched.reconfigure(self.config)
2641 self.registerJobs()
2642
Clark Boylan3ee090a2014-04-03 20:55:09 -07002643 # The pipeline triggers every second, so we should have seen
2644 # several by now.
2645 time.sleep(5)
James E. Blair63bb0ef2013-07-29 17:14:51 -07002646 self.waitUntilSettled()
Clark Boylan3ee090a2014-04-03 20:55:09 -07002647
2648 self.assertEqual(len(self.builds), 2)
2649
James E. Blair63bb0ef2013-07-29 17:14:51 -07002650 port = self.webapp.server.socket.getsockname()[1]
2651
2652 f = urllib.urlopen("http://localhost:%s/status.json" % port)
2653 data = f.read()
2654
2655 self.worker.hold_jobs_in_build = False
Clark Boylan3ee090a2014-04-03 20:55:09 -07002656 # Stop queuing timer triggered jobs so that the assertions
2657 # below don't race against more jobs being queued.
2658 self.config.set('zuul', 'layout_config',
2659 'tests/fixtures/layout-no-timer.yaml')
2660 self.sched.reconfigure(self.config)
2661 self.registerJobs()
James E. Blair63bb0ef2013-07-29 17:14:51 -07002662 self.worker.release()
2663 self.waitUntilSettled()
2664
2665 self.assertEqual(self.getJobFromHistory(
2666 'project-bitrot-stable-old').result, 'SUCCESS')
2667 self.assertEqual(self.getJobFromHistory(
2668 'project-bitrot-stable-older').result, 'SUCCESS')
2669
2670 data = json.loads(data)
2671 status_jobs = set()
2672 for p in data['pipelines']:
2673 for q in p['change_queues']:
2674 for head in q['heads']:
2675 for change in head:
Alex Gaynorddb9ef32013-09-16 21:04:58 -07002676 self.assertEqual(change['id'], None)
James E. Blair63bb0ef2013-07-29 17:14:51 -07002677 for job in change['jobs']:
2678 status_jobs.add(job['name'])
2679 self.assertIn('project-bitrot-stable-old', status_jobs)
2680 self.assertIn('project-bitrot-stable-older', status_jobs)
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002681
James E. Blair4f6033c2014-03-27 15:49:09 -07002682 def test_idle(self):
2683 "Test that frequent periodic jobs work"
2684 self.worker.hold_jobs_in_build = True
James E. Blair4f6033c2014-03-27 15:49:09 -07002685
Clark Boylan3ee090a2014-04-03 20:55:09 -07002686 for x in range(1, 3):
2687 # Test that timer triggers periodic jobs even across
2688 # layout config reloads.
2689 # Start timer trigger
2690 self.config.set('zuul', 'layout_config',
2691 'tests/fixtures/layout-idle.yaml')
2692 self.sched.reconfigure(self.config)
2693 self.registerJobs()
James E. Blair4f6033c2014-03-27 15:49:09 -07002694
Clark Boylan3ee090a2014-04-03 20:55:09 -07002695 # The pipeline triggers every second, so we should have seen
2696 # several by now.
2697 time.sleep(5)
2698 self.waitUntilSettled()
2699
2700 # Stop queuing timer triggered jobs so that the assertions
2701 # below don't race against more jobs being queued.
2702 self.config.set('zuul', 'layout_config',
2703 'tests/fixtures/layout-no-timer.yaml')
2704 self.sched.reconfigure(self.config)
2705 self.registerJobs()
2706
2707 self.assertEqual(len(self.builds), 2)
2708 self.worker.release('.*')
2709 self.waitUntilSettled()
2710 self.assertEqual(len(self.builds), 0)
2711 self.assertEqual(len(self.history), x * 2)
James E. Blair4f6033c2014-03-27 15:49:09 -07002712
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002713 def test_check_smtp_pool(self):
2714 self.config.set('zuul', 'layout_config',
2715 'tests/fixtures/layout-smtp.yaml')
2716 self.sched.reconfigure(self.config)
2717
2718 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2719 self.waitUntilSettled()
2720
2721 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2722 self.waitUntilSettled()
2723
James E. Blairff80a2f2013-12-27 13:24:06 -08002724 self.assertEqual(len(self.smtp_messages), 2)
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002725
2726 # A.messages only holds what FakeGerrit places in it. Thus we
2727 # work on the knowledge of what the first message should be as
2728 # it is only configured to go to SMTP.
2729
2730 self.assertEqual('zuul@example.com',
James E. Blairff80a2f2013-12-27 13:24:06 -08002731 self.smtp_messages[0]['from_email'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002732 self.assertEqual(['you@example.com'],
James E. Blairff80a2f2013-12-27 13:24:06 -08002733 self.smtp_messages[0]['to_email'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002734 self.assertEqual('Starting check jobs.',
James E. Blairff80a2f2013-12-27 13:24:06 -08002735 self.smtp_messages[0]['body'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002736
2737 self.assertEqual('zuul_from@example.com',
James E. Blairff80a2f2013-12-27 13:24:06 -08002738 self.smtp_messages[1]['from_email'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002739 self.assertEqual(['alternative_me@example.com'],
James E. Blairff80a2f2013-12-27 13:24:06 -08002740 self.smtp_messages[1]['to_email'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002741 self.assertEqual(A.messages[0],
James E. Blairff80a2f2013-12-27 13:24:06 -08002742 self.smtp_messages[1]['body'])
James E. Blairad28e912013-11-27 10:43:22 -08002743
James E. Blaire5910202013-12-27 09:50:31 -08002744 def test_timer_smtp(self):
2745 "Test that a periodic job is triggered"
Clark Boylan3ee090a2014-04-03 20:55:09 -07002746 self.worker.hold_jobs_in_build = True
James E. Blaire5910202013-12-27 09:50:31 -08002747 self.config.set('zuul', 'layout_config',
2748 'tests/fixtures/layout-timer-smtp.yaml')
2749 self.sched.reconfigure(self.config)
2750 self.registerJobs()
2751
Clark Boylan3ee090a2014-04-03 20:55:09 -07002752 # The pipeline triggers every second, so we should have seen
2753 # several by now.
2754 time.sleep(5)
James E. Blaire5910202013-12-27 09:50:31 -08002755 self.waitUntilSettled()
2756
Clark Boylan3ee090a2014-04-03 20:55:09 -07002757 self.assertEqual(len(self.builds), 2)
2758 self.worker.release('.*')
2759 self.waitUntilSettled()
2760 self.assertEqual(len(self.history), 2)
2761
James E. Blaire5910202013-12-27 09:50:31 -08002762 self.assertEqual(self.getJobFromHistory(
2763 'project-bitrot-stable-old').result, 'SUCCESS')
2764 self.assertEqual(self.getJobFromHistory(
2765 'project-bitrot-stable-older').result, 'SUCCESS')
2766
James E. Blairff80a2f2013-12-27 13:24:06 -08002767 self.assertEqual(len(self.smtp_messages), 1)
James E. Blaire5910202013-12-27 09:50:31 -08002768
2769 # A.messages only holds what FakeGerrit places in it. Thus we
2770 # work on the knowledge of what the first message should be as
2771 # it is only configured to go to SMTP.
2772
2773 self.assertEqual('zuul_from@example.com',
James E. Blairff80a2f2013-12-27 13:24:06 -08002774 self.smtp_messages[0]['from_email'])
James E. Blaire5910202013-12-27 09:50:31 -08002775 self.assertEqual(['alternative_me@example.com'],
James E. Blairff80a2f2013-12-27 13:24:06 -08002776 self.smtp_messages[0]['to_email'])
James E. Blaire5910202013-12-27 09:50:31 -08002777 self.assertIn('Subject: Periodic check for org/project succeeded',
James E. Blairff80a2f2013-12-27 13:24:06 -08002778 self.smtp_messages[0]['headers'])
James E. Blaire5910202013-12-27 09:50:31 -08002779
Clark Boylan3ee090a2014-04-03 20:55:09 -07002780 # Stop queuing timer triggered jobs and let any that may have
2781 # queued through so that end of test assertions pass.
2782 self.config.set('zuul', 'layout_config',
2783 'tests/fixtures/layout-no-timer.yaml')
2784 self.sched.reconfigure(self.config)
2785 self.registerJobs()
James E. Blairf8058972014-08-15 16:09:16 -07002786 self.waitUntilSettled()
Clark Boylan3ee090a2014-04-03 20:55:09 -07002787 self.worker.release('.*')
2788 self.waitUntilSettled()
2789
James E. Blair91e34592015-07-31 16:45:59 -07002790 def test_client_enqueue_change(self):
James E. Blairad28e912013-11-27 10:43:22 -08002791 "Test that the RPC client can enqueue a change"
2792 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2793 A.addApproval('CRVW', 2)
2794 A.addApproval('APRV', 1)
2795
2796 client = zuul.rpcclient.RPCClient('127.0.0.1',
2797 self.gearman_server.port)
2798 r = client.enqueue(pipeline='gate',
2799 project='org/project',
2800 trigger='gerrit',
James E. Blair36658cf2013-12-06 17:53:48 -08002801 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08002802 self.waitUntilSettled()
2803 self.assertEqual(self.getJobFromHistory('project-merge').result,
2804 'SUCCESS')
2805 self.assertEqual(self.getJobFromHistory('project-test1').result,
2806 'SUCCESS')
2807 self.assertEqual(self.getJobFromHistory('project-test2').result,
2808 'SUCCESS')
2809 self.assertEqual(A.data['status'], 'MERGED')
2810 self.assertEqual(A.reported, 2)
2811 self.assertEqual(r, True)
2812
James E. Blair91e34592015-07-31 16:45:59 -07002813 def test_client_enqueue_ref(self):
2814 "Test that the RPC client can enqueue a ref"
2815
2816 client = zuul.rpcclient.RPCClient('127.0.0.1',
2817 self.gearman_server.port)
2818 r = client.enqueue_ref(
2819 pipeline='post',
2820 project='org/project',
2821 trigger='gerrit',
2822 ref='master',
2823 oldrev='90f173846e3af9154517b88543ffbd1691f31366',
2824 newrev='d479a0bfcb34da57a31adb2a595c0cf687812543')
2825 self.waitUntilSettled()
2826 job_names = [x.name for x in self.history]
2827 self.assertEqual(len(self.history), 1)
2828 self.assertIn('project-post', job_names)
2829 self.assertEqual(r, True)
2830
James E. Blairad28e912013-11-27 10:43:22 -08002831 def test_client_enqueue_negative(self):
2832 "Test that the RPC client returns errors"
2833 client = zuul.rpcclient.RPCClient('127.0.0.1',
2834 self.gearman_server.port)
2835 with testtools.ExpectedException(zuul.rpcclient.RPCFailure,
2836 "Invalid project"):
2837 r = client.enqueue(pipeline='gate',
2838 project='project-does-not-exist',
2839 trigger='gerrit',
James E. Blair36658cf2013-12-06 17:53:48 -08002840 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08002841 client.shutdown()
2842 self.assertEqual(r, False)
2843
2844 with testtools.ExpectedException(zuul.rpcclient.RPCFailure,
2845 "Invalid pipeline"):
2846 r = client.enqueue(pipeline='pipeline-does-not-exist',
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 client.shutdown()
2851 self.assertEqual(r, False)
2852
2853 with testtools.ExpectedException(zuul.rpcclient.RPCFailure,
2854 "Invalid trigger"):
2855 r = client.enqueue(pipeline='gate',
2856 project='org/project',
2857 trigger='trigger-does-not-exist',
James E. Blair36658cf2013-12-06 17:53:48 -08002858 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08002859 client.shutdown()
2860 self.assertEqual(r, False)
2861
2862 with testtools.ExpectedException(zuul.rpcclient.RPCFailure,
2863 "Invalid change"):
2864 r = client.enqueue(pipeline='gate',
2865 project='org/project',
2866 trigger='gerrit',
James E. Blair36658cf2013-12-06 17:53:48 -08002867 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08002868 client.shutdown()
2869 self.assertEqual(r, False)
2870
2871 self.waitUntilSettled()
2872 self.assertEqual(len(self.history), 0)
2873 self.assertEqual(len(self.builds), 0)
James E. Blair36658cf2013-12-06 17:53:48 -08002874
2875 def test_client_promote(self):
2876 "Test that the RPC client can promote a change"
2877 self.worker.hold_jobs_in_build = True
2878 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2879 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2880 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
2881 A.addApproval('CRVW', 2)
2882 B.addApproval('CRVW', 2)
2883 C.addApproval('CRVW', 2)
2884
2885 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2886 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2887 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
2888
2889 self.waitUntilSettled()
2890
Sean Daguef39b9ca2014-01-10 21:34:35 -05002891 items = self.sched.layout.pipelines['gate'].getAllItems()
2892 enqueue_times = {}
2893 for item in items:
2894 enqueue_times[str(item.change)] = item.enqueue_time
2895
James E. Blair36658cf2013-12-06 17:53:48 -08002896 client = zuul.rpcclient.RPCClient('127.0.0.1',
2897 self.gearman_server.port)
2898 r = client.promote(pipeline='gate',
2899 change_ids=['2,1', '3,1'])
2900
Sean Daguef39b9ca2014-01-10 21:34:35 -05002901 # ensure that enqueue times are durable
2902 items = self.sched.layout.pipelines['gate'].getAllItems()
2903 for item in items:
2904 self.assertEqual(
2905 enqueue_times[str(item.change)], item.enqueue_time)
2906
James E. Blair78acec92014-02-06 07:11:32 -08002907 self.waitUntilSettled()
James E. Blair36658cf2013-12-06 17:53:48 -08002908 self.worker.release('.*-merge')
2909 self.waitUntilSettled()
2910 self.worker.release('.*-merge')
2911 self.waitUntilSettled()
2912 self.worker.release('.*-merge')
2913 self.waitUntilSettled()
2914
2915 self.assertEqual(len(self.builds), 6)
2916 self.assertEqual(self.builds[0].name, 'project-test1')
2917 self.assertEqual(self.builds[1].name, 'project-test2')
2918 self.assertEqual(self.builds[2].name, 'project-test1')
2919 self.assertEqual(self.builds[3].name, 'project-test2')
2920 self.assertEqual(self.builds[4].name, 'project-test1')
2921 self.assertEqual(self.builds[5].name, 'project-test2')
2922
2923 self.assertTrue(self.job_has_changes(self.builds[0], B))
2924 self.assertFalse(self.job_has_changes(self.builds[0], A))
2925 self.assertFalse(self.job_has_changes(self.builds[0], C))
2926
2927 self.assertTrue(self.job_has_changes(self.builds[2], B))
2928 self.assertTrue(self.job_has_changes(self.builds[2], C))
2929 self.assertFalse(self.job_has_changes(self.builds[2], A))
2930
2931 self.assertTrue(self.job_has_changes(self.builds[4], B))
2932 self.assertTrue(self.job_has_changes(self.builds[4], C))
2933 self.assertTrue(self.job_has_changes(self.builds[4], A))
2934
2935 self.worker.release()
2936 self.waitUntilSettled()
2937
2938 self.assertEqual(A.data['status'], 'MERGED')
2939 self.assertEqual(A.reported, 2)
2940 self.assertEqual(B.data['status'], 'MERGED')
2941 self.assertEqual(B.reported, 2)
2942 self.assertEqual(C.data['status'], 'MERGED')
2943 self.assertEqual(C.reported, 2)
2944
2945 client.shutdown()
2946 self.assertEqual(r, True)
2947
2948 def test_client_promote_dependent(self):
2949 "Test that the RPC client can promote a dependent change"
2950 # C (depends on B) -> B -> A ; then promote C to get:
2951 # A -> C (depends on B) -> B
2952 self.worker.hold_jobs_in_build = True
2953 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2954 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2955 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
2956
2957 C.setDependsOn(B, 1)
2958
2959 A.addApproval('CRVW', 2)
2960 B.addApproval('CRVW', 2)
2961 C.addApproval('CRVW', 2)
2962
2963 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2964 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2965 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
2966
2967 self.waitUntilSettled()
2968
2969 client = zuul.rpcclient.RPCClient('127.0.0.1',
2970 self.gearman_server.port)
2971 r = client.promote(pipeline='gate',
2972 change_ids=['3,1'])
2973
James E. Blair78acec92014-02-06 07:11:32 -08002974 self.waitUntilSettled()
James E. Blair36658cf2013-12-06 17:53:48 -08002975 self.worker.release('.*-merge')
2976 self.waitUntilSettled()
2977 self.worker.release('.*-merge')
2978 self.waitUntilSettled()
2979 self.worker.release('.*-merge')
2980 self.waitUntilSettled()
2981
2982 self.assertEqual(len(self.builds), 6)
2983 self.assertEqual(self.builds[0].name, 'project-test1')
2984 self.assertEqual(self.builds[1].name, 'project-test2')
2985 self.assertEqual(self.builds[2].name, 'project-test1')
2986 self.assertEqual(self.builds[3].name, 'project-test2')
2987 self.assertEqual(self.builds[4].name, 'project-test1')
2988 self.assertEqual(self.builds[5].name, 'project-test2')
2989
2990 self.assertTrue(self.job_has_changes(self.builds[0], B))
2991 self.assertFalse(self.job_has_changes(self.builds[0], A))
2992 self.assertFalse(self.job_has_changes(self.builds[0], C))
2993
2994 self.assertTrue(self.job_has_changes(self.builds[2], B))
2995 self.assertTrue(self.job_has_changes(self.builds[2], C))
2996 self.assertFalse(self.job_has_changes(self.builds[2], A))
2997
2998 self.assertTrue(self.job_has_changes(self.builds[4], B))
2999 self.assertTrue(self.job_has_changes(self.builds[4], C))
3000 self.assertTrue(self.job_has_changes(self.builds[4], A))
3001
3002 self.worker.release()
3003 self.waitUntilSettled()
3004
3005 self.assertEqual(A.data['status'], 'MERGED')
3006 self.assertEqual(A.reported, 2)
3007 self.assertEqual(B.data['status'], 'MERGED')
3008 self.assertEqual(B.reported, 2)
3009 self.assertEqual(C.data['status'], 'MERGED')
3010 self.assertEqual(C.reported, 2)
3011
3012 client.shutdown()
3013 self.assertEqual(r, True)
3014
3015 def test_client_promote_negative(self):
3016 "Test that the RPC client returns errors for promotion"
3017 self.worker.hold_jobs_in_build = True
3018 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3019 A.addApproval('CRVW', 2)
3020 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3021 self.waitUntilSettled()
3022
3023 client = zuul.rpcclient.RPCClient('127.0.0.1',
3024 self.gearman_server.port)
3025
3026 with testtools.ExpectedException(zuul.rpcclient.RPCFailure):
3027 r = client.promote(pipeline='nonexistent',
3028 change_ids=['2,1', '3,1'])
3029 client.shutdown()
3030 self.assertEqual(r, False)
3031
3032 with testtools.ExpectedException(zuul.rpcclient.RPCFailure):
3033 r = client.promote(pipeline='gate',
3034 change_ids=['4,1'])
3035 client.shutdown()
3036 self.assertEqual(r, False)
3037
3038 self.worker.hold_jobs_in_build = False
3039 self.worker.release()
3040 self.waitUntilSettled()
Clark Boylan7603a372014-01-21 11:43:20 -08003041
3042 def test_queue_rate_limiting(self):
3043 "Test that DependentPipelines are rate limited with dep across window"
3044 self.config.set('zuul', 'layout_config',
3045 'tests/fixtures/layout-rate-limit.yaml')
3046 self.sched.reconfigure(self.config)
3047 self.worker.hold_jobs_in_build = True
3048 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3049 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
3050 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
3051
3052 C.setDependsOn(B, 1)
3053 self.worker.addFailTest('project-test1', A)
3054
3055 A.addApproval('CRVW', 2)
3056 B.addApproval('CRVW', 2)
3057 C.addApproval('CRVW', 2)
3058
3059 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3060 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3061 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
3062 self.waitUntilSettled()
3063
3064 # Only A and B will have their merge jobs queued because
3065 # window is 2.
3066 self.assertEqual(len(self.builds), 2)
3067 self.assertEqual(self.builds[0].name, 'project-merge')
3068 self.assertEqual(self.builds[1].name, 'project-merge')
3069
3070 self.worker.release('.*-merge')
3071 self.waitUntilSettled()
3072 self.worker.release('.*-merge')
3073 self.waitUntilSettled()
3074
3075 # Only A and B will have their test jobs queued because
3076 # window is 2.
3077 self.assertEqual(len(self.builds), 4)
3078 self.assertEqual(self.builds[0].name, 'project-test1')
3079 self.assertEqual(self.builds[1].name, 'project-test2')
3080 self.assertEqual(self.builds[2].name, 'project-test1')
3081 self.assertEqual(self.builds[3].name, 'project-test2')
3082
3083 self.worker.release('project-.*')
3084 self.waitUntilSettled()
3085
3086 queue = self.sched.layout.pipelines['gate'].queues[0]
3087 # A failed so window is reduced by 1 to 1.
3088 self.assertEqual(queue.window, 1)
3089 self.assertEqual(queue.window_floor, 1)
3090 self.assertEqual(A.data['status'], 'NEW')
3091
3092 # Gate is reset and only B's merge job is queued because
3093 # window shrunk to 1.
3094 self.assertEqual(len(self.builds), 1)
3095 self.assertEqual(self.builds[0].name, 'project-merge')
3096
3097 self.worker.release('.*-merge')
3098 self.waitUntilSettled()
3099
3100 # Only B's test jobs are queued because window is still 1.
3101 self.assertEqual(len(self.builds), 2)
3102 self.assertEqual(self.builds[0].name, 'project-test1')
3103 self.assertEqual(self.builds[1].name, 'project-test2')
3104
3105 self.worker.release('project-.*')
3106 self.waitUntilSettled()
3107
3108 # B was successfully merged so window is increased to 2.
3109 self.assertEqual(queue.window, 2)
3110 self.assertEqual(queue.window_floor, 1)
3111 self.assertEqual(B.data['status'], 'MERGED')
3112
3113 # Only C is left and its merge job is queued.
3114 self.assertEqual(len(self.builds), 1)
3115 self.assertEqual(self.builds[0].name, 'project-merge')
3116
3117 self.worker.release('.*-merge')
3118 self.waitUntilSettled()
3119
3120 # After successful merge job the test jobs for C are queued.
3121 self.assertEqual(len(self.builds), 2)
3122 self.assertEqual(self.builds[0].name, 'project-test1')
3123 self.assertEqual(self.builds[1].name, 'project-test2')
3124
3125 self.worker.release('project-.*')
3126 self.waitUntilSettled()
3127
3128 # C successfully merged so window is bumped to 3.
3129 self.assertEqual(queue.window, 3)
3130 self.assertEqual(queue.window_floor, 1)
3131 self.assertEqual(C.data['status'], 'MERGED')
3132
3133 def test_queue_rate_limiting_dependent(self):
3134 "Test that DependentPipelines are rate limited with dep in window"
3135 self.config.set('zuul', 'layout_config',
3136 'tests/fixtures/layout-rate-limit.yaml')
3137 self.sched.reconfigure(self.config)
3138 self.worker.hold_jobs_in_build = True
3139 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3140 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
3141 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
3142
3143 B.setDependsOn(A, 1)
3144
3145 self.worker.addFailTest('project-test1', A)
3146
3147 A.addApproval('CRVW', 2)
3148 B.addApproval('CRVW', 2)
3149 C.addApproval('CRVW', 2)
3150
3151 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3152 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3153 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
3154 self.waitUntilSettled()
3155
3156 # Only A and B will have their merge jobs queued because
3157 # window is 2.
3158 self.assertEqual(len(self.builds), 2)
3159 self.assertEqual(self.builds[0].name, 'project-merge')
3160 self.assertEqual(self.builds[1].name, 'project-merge')
3161
3162 self.worker.release('.*-merge')
3163 self.waitUntilSettled()
3164 self.worker.release('.*-merge')
3165 self.waitUntilSettled()
3166
3167 # Only A and B will have their test jobs queued because
3168 # window is 2.
3169 self.assertEqual(len(self.builds), 4)
3170 self.assertEqual(self.builds[0].name, 'project-test1')
3171 self.assertEqual(self.builds[1].name, 'project-test2')
3172 self.assertEqual(self.builds[2].name, 'project-test1')
3173 self.assertEqual(self.builds[3].name, 'project-test2')
3174
3175 self.worker.release('project-.*')
3176 self.waitUntilSettled()
3177
3178 queue = self.sched.layout.pipelines['gate'].queues[0]
3179 # A failed so window is reduced by 1 to 1.
3180 self.assertEqual(queue.window, 1)
3181 self.assertEqual(queue.window_floor, 1)
3182 self.assertEqual(A.data['status'], 'NEW')
3183 self.assertEqual(B.data['status'], 'NEW')
3184
3185 # Gate is reset and only C's merge job is queued because
3186 # window shrunk to 1 and A and B were dequeued.
3187 self.assertEqual(len(self.builds), 1)
3188 self.assertEqual(self.builds[0].name, 'project-merge')
3189
3190 self.worker.release('.*-merge')
3191 self.waitUntilSettled()
3192
3193 # Only C's test jobs are queued because window is still 1.
3194 self.assertEqual(len(self.builds), 2)
3195 self.assertEqual(self.builds[0].name, 'project-test1')
3196 self.assertEqual(self.builds[1].name, 'project-test2')
3197
3198 self.worker.release('project-.*')
3199 self.waitUntilSettled()
3200
3201 # C was successfully merged so window is increased to 2.
3202 self.assertEqual(queue.window, 2)
3203 self.assertEqual(queue.window_floor, 1)
3204 self.assertEqual(C.data['status'], 'MERGED')
Joshua Heskethba8776a2014-01-12 14:35:40 +08003205
3206 def test_worker_update_metadata(self):
3207 "Test if a worker can send back metadata about itself"
3208 self.worker.hold_jobs_in_build = True
3209
3210 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3211 A.addApproval('CRVW', 2)
3212 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3213 self.waitUntilSettled()
3214
3215 self.assertEqual(len(self.launcher.builds), 1)
3216
3217 self.log.debug('Current builds:')
3218 self.log.debug(self.launcher.builds)
3219
3220 start = time.time()
3221 while True:
3222 if time.time() - start > 10:
3223 raise Exception("Timeout waiting for gearman server to report "
3224 + "back to the client")
3225 build = self.launcher.builds.values()[0]
3226 if build.worker.name == "My Worker":
3227 break
3228 else:
3229 time.sleep(0)
3230
3231 self.log.debug(build)
3232 self.assertEqual("My Worker", build.worker.name)
3233 self.assertEqual("localhost", build.worker.hostname)
3234 self.assertEqual(['127.0.0.1', '192.168.1.1'], build.worker.ips)
3235 self.assertEqual("zuul.example.org", build.worker.fqdn)
3236 self.assertEqual("FakeBuilder", build.worker.program)
3237 self.assertEqual("v1.1", build.worker.version)
3238 self.assertEqual({'something': 'else'}, build.worker.extra)
3239
3240 self.worker.hold_jobs_in_build = False
3241 self.worker.release()
3242 self.waitUntilSettled()
Joshua Hesketh3979e3e2014-03-04 11:21:10 +11003243
3244 def test_footer_message(self):
3245 "Test a pipeline's footer message is correctly added to the report."
3246 self.config.set('zuul', 'layout_config',
3247 'tests/fixtures/layout-footer-message.yaml')
3248 self.sched.reconfigure(self.config)
3249 self.registerJobs()
3250
3251 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3252 A.addApproval('CRVW', 2)
3253 self.worker.addFailTest('test1', A)
3254 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3255 self.waitUntilSettled()
3256
3257 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
3258 B.addApproval('CRVW', 2)
3259 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3260 self.waitUntilSettled()
3261
3262 self.assertEqual(2, len(self.smtp_messages))
3263
3264 failure_body = """\
3265Build failed. For information on how to proceed, see \
3266http://wiki.example.org/Test_Failures
3267
3268- test1 http://logs.example.com/1/1/gate/test1/0 : FAILURE in 0s
3269- test2 http://logs.example.com/1/1/gate/test2/1 : SUCCESS in 0s
3270
3271For CI problems and help debugging, contact ci@example.org"""
3272
3273 success_body = """\
3274Build succeeded.
3275
3276- test1 http://logs.example.com/2/1/gate/test1/2 : SUCCESS in 0s
3277- test2 http://logs.example.com/2/1/gate/test2/3 : SUCCESS in 0s
3278
3279For CI problems and help debugging, contact ci@example.org"""
3280
3281 self.assertEqual(failure_body, self.smtp_messages[0]['body'])
3282 self.assertEqual(success_body, self.smtp_messages[1]['body'])
Joshua Heskethb7179772014-01-30 23:30:46 +11003283
3284 def test_merge_failure_reporters(self):
3285 """Check that the config is set up correctly"""
3286
3287 self.config.set('zuul', 'layout_config',
3288 'tests/fixtures/layout-merge-failure.yaml')
3289 self.sched.reconfigure(self.config)
3290 self.registerJobs()
3291
3292 self.assertEqual(
Jeremy Stanley1c2c3c22015-06-15 21:23:19 +00003293 "Merge Failed.\n\nThis change or one of its cross-repo "
3294 "dependencies was unable to be automatically merged with the "
3295 "current state of its repository. Please rebase the change and "
3296 "upload a new patchset.",
Joshua Heskethb7179772014-01-30 23:30:46 +11003297 self.sched.layout.pipelines['check'].merge_failure_message)
3298 self.assertEqual(
3299 "The merge failed! For more information...",
3300 self.sched.layout.pipelines['gate'].merge_failure_message)
3301
3302 self.assertEqual(
3303 len(self.sched.layout.pipelines['check'].merge_failure_actions), 1)
3304 self.assertEqual(
3305 len(self.sched.layout.pipelines['gate'].merge_failure_actions), 2)
3306
3307 self.assertTrue(isinstance(
3308 self.sched.layout.pipelines['check'].merge_failure_actions[0].
3309 reporter, zuul.reporter.gerrit.Reporter))
3310
3311 self.assertTrue(
3312 (
3313 isinstance(self.sched.layout.pipelines['gate'].
3314 merge_failure_actions[0].reporter,
3315 zuul.reporter.smtp.Reporter) and
3316 isinstance(self.sched.layout.pipelines['gate'].
3317 merge_failure_actions[1].reporter,
3318 zuul.reporter.gerrit.Reporter)
3319 ) or (
3320 isinstance(self.sched.layout.pipelines['gate'].
3321 merge_failure_actions[0].reporter,
3322 zuul.reporter.gerrit.Reporter) and
3323 isinstance(self.sched.layout.pipelines['gate'].
3324 merge_failure_actions[1].reporter,
3325 zuul.reporter.smtp.Reporter)
3326 )
3327 )
3328
3329 def test_merge_failure_reports(self):
3330 """Check that when a change fails to merge the correct message is sent
3331 to the correct reporter"""
3332 self.config.set('zuul', 'layout_config',
3333 'tests/fixtures/layout-merge-failure.yaml')
3334 self.sched.reconfigure(self.config)
3335 self.registerJobs()
3336
3337 # Check a test failure isn't reported to SMTP
3338 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3339 A.addApproval('CRVW', 2)
3340 self.worker.addFailTest('project-test1', A)
3341 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3342 self.waitUntilSettled()
3343
3344 self.assertEqual(3, len(self.history)) # 3 jobs
3345 self.assertEqual(0, len(self.smtp_messages))
3346
3347 # Check a merge failure is reported to SMTP
3348 # B should be merged, but C will conflict with B
3349 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
3350 B.addPatchset(['conflict'])
3351 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
3352 C.addPatchset(['conflict'])
3353 B.addApproval('CRVW', 2)
3354 C.addApproval('CRVW', 2)
3355 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3356 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
3357 self.waitUntilSettled()
3358
3359 self.assertEqual(6, len(self.history)) # A and B jobs
3360 self.assertEqual(1, len(self.smtp_messages))
3361 self.assertEqual('The merge failed! For more information...',
3362 self.smtp_messages[0]['body'])
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11003363
3364 def test_swift_instructions(self):
3365 "Test that the correct swift instructions are sent to the workers"
3366 self.config.set('zuul', 'layout_config',
3367 'tests/fixtures/layout-swift.yaml')
3368 self.sched.reconfigure(self.config)
3369 self.registerJobs()
3370
3371 self.worker.hold_jobs_in_build = True
3372 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3373
3374 A.addApproval('CRVW', 2)
3375 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3376 self.waitUntilSettled()
3377
3378 self.assertEqual(
3379 "https://storage.example.org/V1/AUTH_account/merge_logs/1/1/1/"
3380 "gate/test-merge/",
Joshua Hesketh76dee532014-07-03 15:39:13 +10003381 self.builds[0].parameters['SWIFT_logs_URL'][:-7])
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11003382 self.assertEqual(5,
3383 len(self.builds[0].parameters['SWIFT_logs_HMAC_BODY'].
3384 split('\n')))
3385 self.assertIn('SWIFT_logs_SIGNATURE', self.builds[0].parameters)
3386
3387 self.assertEqual(
3388 "https://storage.example.org/V1/AUTH_account/logs/1/1/1/"
3389 "gate/test-test/",
Joshua Hesketh76dee532014-07-03 15:39:13 +10003390 self.builds[1].parameters['SWIFT_logs_URL'][:-7])
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11003391 self.assertEqual(5,
3392 len(self.builds[1].parameters['SWIFT_logs_HMAC_BODY'].
3393 split('\n')))
3394 self.assertIn('SWIFT_logs_SIGNATURE', self.builds[1].parameters)
3395
3396 self.assertEqual(
3397 "https://storage.example.org/V1/AUTH_account/stash/1/1/1/"
3398 "gate/test-test/",
Joshua Hesketh76dee532014-07-03 15:39:13 +10003399 self.builds[1].parameters['SWIFT_MOSTLY_URL'][:-7])
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11003400 self.assertEqual(5,
3401 len(self.builds[1].
3402 parameters['SWIFT_MOSTLY_HMAC_BODY'].split('\n')))
3403 self.assertIn('SWIFT_MOSTLY_SIGNATURE', self.builds[1].parameters)
3404
3405 self.worker.hold_jobs_in_build = False
3406 self.worker.release()
3407 self.waitUntilSettled()
Joshua Hesketh85af4e92014-02-21 08:28:58 -08003408
3409 def test_client_get_running_jobs(self):
3410 "Test that the RPC client can get a list of running jobs"
3411 self.worker.hold_jobs_in_build = True
3412 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3413 A.addApproval('CRVW', 2)
3414 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3415 self.waitUntilSettled()
3416
3417 client = zuul.rpcclient.RPCClient('127.0.0.1',
3418 self.gearman_server.port)
3419
3420 # Wait for gearman server to send the initial workData back to zuul
3421 start = time.time()
3422 while True:
3423 if time.time() - start > 10:
3424 raise Exception("Timeout waiting for gearman server to report "
3425 + "back to the client")
3426 build = self.launcher.builds.values()[0]
3427 if build.worker.name == "My Worker":
3428 break
3429 else:
3430 time.sleep(0)
3431
3432 running_items = client.get_running_jobs()
3433
3434 self.assertEqual(1, len(running_items))
3435 running_item = running_items[0]
3436 self.assertEqual([], running_item['failing_reasons'])
3437 self.assertEqual([], running_item['items_behind'])
3438 self.assertEqual('https://hostname/1', running_item['url'])
3439 self.assertEqual(None, running_item['item_ahead'])
3440 self.assertEqual('org/project', running_item['project'])
3441 self.assertEqual(None, running_item['remaining_time'])
3442 self.assertEqual(True, running_item['active'])
3443 self.assertEqual('1,1', running_item['id'])
3444
3445 self.assertEqual(3, len(running_item['jobs']))
3446 for job in running_item['jobs']:
3447 if job['name'] == 'project-merge':
3448 self.assertEqual('project-merge', job['name'])
3449 self.assertEqual('gate', job['pipeline'])
3450 self.assertEqual(False, job['retry'])
Joshua Hesketh85af4e92014-02-21 08:28:58 -08003451 self.assertEqual('https://server/job/project-merge/0/',
3452 job['url'])
3453 self.assertEqual(7, len(job['worker']))
3454 self.assertEqual(False, job['canceled'])
3455 self.assertEqual(True, job['voting'])
3456 self.assertEqual(None, job['result'])
3457 self.assertEqual('gate', job['pipeline'])
3458 break
3459
3460 self.worker.hold_jobs_in_build = False
3461 self.worker.release()
3462 self.waitUntilSettled()
3463
3464 running_items = client.get_running_jobs()
3465 self.assertEqual(0, len(running_items))
James E. Blairbadc1ad2014-04-28 13:55:14 -07003466
3467 def test_nonvoting_pipeline(self):
3468 "Test that a nonvoting pipeline (experimental) can still report"
3469
Joshua Heskethcc017ea2014-04-30 19:55:25 +10003470 A = self.fake_gerrit.addFakeChange('org/experimental-project',
3471 'master', 'A')
James E. Blairbadc1ad2014-04-28 13:55:14 -07003472 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3473 self.waitUntilSettled()
Joshua Heskethcc017ea2014-04-30 19:55:25 +10003474 self.assertEqual(
3475 self.getJobFromHistory('experimental-project-test').result,
3476 'SUCCESS')
James E. Blairbadc1ad2014-04-28 13:55:14 -07003477 self.assertEqual(A.reported, 1)
James E. Blair5ee24252014-12-30 10:12:29 -08003478
3479 def test_crd_gate(self):
3480 "Test cross-repo dependencies"
3481 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3482 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3483 A.addApproval('CRVW', 2)
3484 B.addApproval('CRVW', 2)
3485
3486 AM2 = self.fake_gerrit.addFakeChange('org/project1', 'master', 'AM2')
3487 AM1 = self.fake_gerrit.addFakeChange('org/project1', 'master', 'AM1')
3488 AM2.setMerged()
3489 AM1.setMerged()
3490
3491 BM2 = self.fake_gerrit.addFakeChange('org/project2', 'master', 'BM2')
3492 BM1 = self.fake_gerrit.addFakeChange('org/project2', 'master', 'BM1')
3493 BM2.setMerged()
3494 BM1.setMerged()
3495
3496 # A -> AM1 -> AM2
3497 # B -> BM1 -> BM2
3498 # A Depends-On: B
3499 # M2 is here to make sure it is never queried. If it is, it
3500 # means zuul is walking down the entire history of merged
3501 # changes.
3502
3503 B.setDependsOn(BM1, 1)
3504 BM1.setDependsOn(BM2, 1)
3505
3506 A.setDependsOn(AM1, 1)
3507 AM1.setDependsOn(AM2, 1)
3508
3509 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3510 A.subject, B.data['id'])
3511
3512 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3513 self.waitUntilSettled()
3514
3515 self.assertEqual(A.data['status'], 'NEW')
3516 self.assertEqual(B.data['status'], 'NEW')
3517
3518 source = self.sched.layout.pipelines['gate'].source
3519 source.maintainCache([])
3520
3521 self.worker.hold_jobs_in_build = True
3522 B.addApproval('APRV', 1)
3523 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3524 self.waitUntilSettled()
3525
3526 self.worker.release('.*-merge')
3527 self.waitUntilSettled()
3528 self.worker.release('.*-merge')
3529 self.waitUntilSettled()
3530 self.worker.hold_jobs_in_build = False
3531 self.worker.release()
3532 self.waitUntilSettled()
3533
3534 self.assertEqual(AM2.queried, 0)
3535 self.assertEqual(BM2.queried, 0)
3536 self.assertEqual(A.data['status'], 'MERGED')
3537 self.assertEqual(B.data['status'], 'MERGED')
3538 self.assertEqual(A.reported, 2)
3539 self.assertEqual(B.reported, 2)
3540
James E. Blair8f78d882015-02-05 08:51:37 -08003541 self.assertEqual(self.getJobFromHistory('project1-merge').changes,
3542 '2,1 1,1')
3543
3544 def test_crd_branch(self):
3545 "Test cross-repo dependencies in multiple branches"
3546 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3547 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3548 C = self.fake_gerrit.addFakeChange('org/project2', 'mp', 'C')
3549 C.data['id'] = B.data['id']
3550 A.addApproval('CRVW', 2)
3551 B.addApproval('CRVW', 2)
3552 C.addApproval('CRVW', 2)
3553
3554 # A Depends-On: B+C
3555 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3556 A.subject, B.data['id'])
3557
3558 self.worker.hold_jobs_in_build = True
3559 B.addApproval('APRV', 1)
3560 C.addApproval('APRV', 1)
3561 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3562 self.waitUntilSettled()
3563
3564 self.worker.release('.*-merge')
3565 self.waitUntilSettled()
3566 self.worker.release('.*-merge')
3567 self.waitUntilSettled()
3568 self.worker.release('.*-merge')
3569 self.waitUntilSettled()
3570 self.worker.hold_jobs_in_build = False
3571 self.worker.release()
3572 self.waitUntilSettled()
3573
3574 self.assertEqual(A.data['status'], 'MERGED')
3575 self.assertEqual(B.data['status'], 'MERGED')
3576 self.assertEqual(C.data['status'], 'MERGED')
3577 self.assertEqual(A.reported, 2)
3578 self.assertEqual(B.reported, 2)
3579 self.assertEqual(C.reported, 2)
3580
3581 self.assertEqual(self.getJobFromHistory('project1-merge').changes,
3582 '2,1 3,1 1,1')
3583
3584 def test_crd_multiline(self):
3585 "Test multiple depends-on lines in commit"
3586 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3587 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3588 C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
3589 A.addApproval('CRVW', 2)
3590 B.addApproval('CRVW', 2)
3591 C.addApproval('CRVW', 2)
3592
3593 # A Depends-On: B+C
3594 A.data['commitMessage'] = '%s\n\nDepends-On: %s\nDepends-On: %s\n' % (
3595 A.subject, B.data['id'], C.data['id'])
3596
3597 self.worker.hold_jobs_in_build = True
3598 B.addApproval('APRV', 1)
3599 C.addApproval('APRV', 1)
3600 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3601 self.waitUntilSettled()
3602
3603 self.worker.release('.*-merge')
3604 self.waitUntilSettled()
3605 self.worker.release('.*-merge')
3606 self.waitUntilSettled()
3607 self.worker.release('.*-merge')
3608 self.waitUntilSettled()
3609 self.worker.hold_jobs_in_build = False
3610 self.worker.release()
3611 self.waitUntilSettled()
3612
3613 self.assertEqual(A.data['status'], 'MERGED')
3614 self.assertEqual(B.data['status'], 'MERGED')
3615 self.assertEqual(C.data['status'], 'MERGED')
3616 self.assertEqual(A.reported, 2)
3617 self.assertEqual(B.reported, 2)
3618 self.assertEqual(C.reported, 2)
3619
3620 self.assertEqual(self.getJobFromHistory('project1-merge').changes,
3621 '2,1 3,1 1,1')
James E. Blair5ee24252014-12-30 10:12:29 -08003622
3623 def test_crd_unshared_gate(self):
3624 "Test cross-repo dependencies in unshared gate queues"
3625 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3626 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
3627 A.addApproval('CRVW', 2)
3628 B.addApproval('CRVW', 2)
3629
3630 # A Depends-On: B
3631 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3632 A.subject, B.data['id'])
3633
3634 # A and B do not share a queue, make sure that A is unable to
3635 # enqueue B (and therefore, A is unable to be enqueued).
3636 B.addApproval('APRV', 1)
3637 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3638 self.waitUntilSettled()
3639
3640 self.assertEqual(A.data['status'], 'NEW')
3641 self.assertEqual(B.data['status'], 'NEW')
3642 self.assertEqual(A.reported, 0)
3643 self.assertEqual(B.reported, 0)
3644 self.assertEqual(len(self.history), 0)
3645
3646 # Enqueue and merge B alone.
3647 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3648 self.waitUntilSettled()
3649
3650 self.assertEqual(B.data['status'], 'MERGED')
3651 self.assertEqual(B.reported, 2)
3652
3653 # Now that B is merged, A should be able to be enqueued and
3654 # merged.
3655 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3656 self.waitUntilSettled()
3657
3658 self.assertEqual(A.data['status'], 'MERGED')
3659 self.assertEqual(A.reported, 2)
3660
James E. Blair96698e22015-04-02 07:48:21 -07003661 def test_crd_gate_reverse(self):
3662 "Test reverse cross-repo dependencies"
3663 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3664 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3665 A.addApproval('CRVW', 2)
3666 B.addApproval('CRVW', 2)
3667
3668 # A Depends-On: B
3669
3670 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3671 A.subject, B.data['id'])
3672
3673 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3674 self.waitUntilSettled()
3675
3676 self.assertEqual(A.data['status'], 'NEW')
3677 self.assertEqual(B.data['status'], 'NEW')
3678
3679 self.worker.hold_jobs_in_build = True
3680 A.addApproval('APRV', 1)
3681 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3682 self.waitUntilSettled()
3683
3684 self.worker.release('.*-merge')
3685 self.waitUntilSettled()
3686 self.worker.release('.*-merge')
3687 self.waitUntilSettled()
3688 self.worker.hold_jobs_in_build = False
3689 self.worker.release()
3690 self.waitUntilSettled()
3691
3692 self.assertEqual(A.data['status'], 'MERGED')
3693 self.assertEqual(B.data['status'], 'MERGED')
3694 self.assertEqual(A.reported, 2)
3695 self.assertEqual(B.reported, 2)
3696
3697 self.assertEqual(self.getJobFromHistory('project1-merge').changes,
3698 '2,1 1,1')
3699
James E. Blair5ee24252014-12-30 10:12:29 -08003700 def test_crd_cycle(self):
3701 "Test cross-repo dependency cycles"
3702 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3703 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3704 A.addApproval('CRVW', 2)
3705 B.addApproval('CRVW', 2)
3706
3707 # A -> B -> A (via commit-depends)
3708
3709 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3710 A.subject, B.data['id'])
3711 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3712 B.subject, A.data['id'])
3713
3714 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3715 self.waitUntilSettled()
3716
3717 self.assertEqual(A.reported, 0)
3718 self.assertEqual(B.reported, 0)
3719 self.assertEqual(A.data['status'], 'NEW')
3720 self.assertEqual(B.data['status'], 'NEW')
James E. Blairbfb8e042014-12-30 17:01:44 -08003721
Evgeny Antyshev0deaaad2015-08-03 20:22:56 +00003722 def test_crd_gate_unknown(self):
3723 "Test unknown projects in dependent pipeline"
3724 self.init_repo("org/unknown")
3725 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3726 B = self.fake_gerrit.addFakeChange('org/unknown', 'master', 'B')
3727 A.addApproval('CRVW', 2)
3728 B.addApproval('CRVW', 2)
3729
3730 # A Depends-On: B
3731 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3732 A.subject, B.data['id'])
3733
3734 B.addApproval('APRV', 1)
3735 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3736 self.waitUntilSettled()
3737
3738 # Unknown projects cannot share a queue with any other
3739 # since they don't have common jobs with any other (they have no jobs).
3740 # Changes which depend on unknown project changes
3741 # should not be processed in dependent pipeline
3742 self.assertEqual(A.data['status'], 'NEW')
3743 self.assertEqual(B.data['status'], 'NEW')
3744 self.assertEqual(A.reported, 0)
3745 self.assertEqual(B.reported, 0)
3746 self.assertEqual(len(self.history), 0)
3747
3748 # Simulate change B being gated outside this layout
3749 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3750 B.setMerged()
3751 self.waitUntilSettled()
3752 self.assertEqual(len(self.history), 0)
3753
3754 # Now that B is merged, A should be able to be enqueued and
3755 # merged.
3756 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3757 self.waitUntilSettled()
3758
3759 self.assertEqual(A.data['status'], 'MERGED')
3760 self.assertEqual(A.reported, 2)
3761 self.assertEqual(B.data['status'], 'MERGED')
3762 self.assertEqual(B.reported, 0)
3763
James E. Blairbfb8e042014-12-30 17:01:44 -08003764 def test_crd_check(self):
3765 "Test cross-repo dependencies in independent pipelines"
3766
3767 self.gearman_server.hold_jobs_in_queue = True
3768 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3769 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3770
3771 # A Depends-On: B
3772 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3773 A.subject, B.data['id'])
3774
3775 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3776 self.waitUntilSettled()
3777
3778 queue = self.gearman_server.getQueue()
3779 ref = self.getParameter(queue[-1], 'ZUUL_REF')
3780 self.gearman_server.hold_jobs_in_queue = False
3781 self.gearman_server.release()
3782 self.waitUntilSettled()
3783
3784 path = os.path.join(self.git_root, "org/project1")
3785 repo = git.Repo(path)
3786 repo_messages = [c.message.strip() for c in repo.iter_commits(ref)]
3787 repo_messages.reverse()
3788 correct_messages = ['initial commit', 'A-1']
3789 self.assertEqual(repo_messages, correct_messages)
3790
3791 path = os.path.join(self.git_root, "org/project2")
3792 repo = git.Repo(path)
3793 repo_messages = [c.message.strip() for c in repo.iter_commits(ref)]
3794 repo_messages.reverse()
3795 correct_messages = ['initial commit', 'B-1']
3796 self.assertEqual(repo_messages, correct_messages)
3797
3798 self.assertEqual(A.data['status'], 'NEW')
3799 self.assertEqual(B.data['status'], 'NEW')
3800 self.assertEqual(A.reported, 1)
3801 self.assertEqual(B.reported, 0)
3802
3803 self.assertEqual(self.history[0].changes, '2,1 1,1')
3804 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 0)
James E. Blair8f78d882015-02-05 08:51:37 -08003805
James E. Blairdbfe1cd2015-02-07 11:41:19 -08003806 def test_crd_check_git_depends(self):
3807 "Test single-repo dependencies in independent pipelines"
James E. Blairb8c16472015-05-05 14:55:26 -07003808 self.gearman_server.hold_jobs_in_build = True
James E. Blairdbfe1cd2015-02-07 11:41:19 -08003809 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3810 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
3811
3812 # Add two git-dependent changes and make sure they both report
3813 # success.
3814 B.setDependsOn(A, 1)
3815 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3816 self.waitUntilSettled()
3817 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
3818 self.waitUntilSettled()
3819
James E. Blairb8c16472015-05-05 14:55:26 -07003820 self.orderedRelease()
3821 self.gearman_server.hold_jobs_in_build = False
James E. Blairdbfe1cd2015-02-07 11:41:19 -08003822 self.waitUntilSettled()
3823
3824 self.assertEqual(A.data['status'], 'NEW')
3825 self.assertEqual(B.data['status'], 'NEW')
3826 self.assertEqual(A.reported, 1)
3827 self.assertEqual(B.reported, 1)
3828
3829 self.assertEqual(self.history[0].changes, '1,1')
3830 self.assertEqual(self.history[-1].changes, '1,1 2,1')
3831 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 0)
3832
3833 self.assertIn('Build succeeded', A.messages[0])
3834 self.assertIn('Build succeeded', B.messages[0])
3835
3836 def test_crd_check_duplicate(self):
3837 "Test duplicate check in independent pipelines"
James E. Blair1e263032015-05-07 14:35:34 -07003838 self.worker.hold_jobs_in_build = True
James E. Blairdbfe1cd2015-02-07 11:41:19 -08003839 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3840 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
3841 check_pipeline = self.sched.layout.pipelines['check']
3842
3843 # Add two git-dependent changes...
3844 B.setDependsOn(A, 1)
3845 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
3846 self.waitUntilSettled()
3847 self.assertEqual(len(check_pipeline.getAllItems()), 2)
3848
3849 # ...make sure the live one is not duplicated...
3850 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
3851 self.waitUntilSettled()
3852 self.assertEqual(len(check_pipeline.getAllItems()), 2)
3853
3854 # ...but the non-live one is able to be.
3855 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3856 self.waitUntilSettled()
3857 self.assertEqual(len(check_pipeline.getAllItems()), 3)
3858
Clark Boylandd849822015-03-02 12:38:14 -08003859 # Release jobs in order to avoid races with change A jobs
3860 # finishing before change B jobs.
James E. Blaird7650852015-05-07 15:47:37 -07003861 self.orderedRelease()
James E. Blair1e263032015-05-07 14:35:34 -07003862 self.worker.hold_jobs_in_build = False
3863 self.worker.release()
James E. Blairdbfe1cd2015-02-07 11:41:19 -08003864 self.waitUntilSettled()
3865
3866 self.assertEqual(A.data['status'], 'NEW')
3867 self.assertEqual(B.data['status'], 'NEW')
3868 self.assertEqual(A.reported, 1)
3869 self.assertEqual(B.reported, 1)
3870
3871 self.assertEqual(self.history[0].changes, '1,1 2,1')
3872 self.assertEqual(self.history[1].changes, '1,1')
3873 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 0)
3874
3875 self.assertIn('Build succeeded', A.messages[0])
3876 self.assertIn('Build succeeded', B.messages[0])
3877
Evgeny Antyshev0deaaad2015-08-03 20:22:56 +00003878 def _test_crd_check_reconfiguration(self, project1, project2):
James E. Blair8f78d882015-02-05 08:51:37 -08003879 "Test cross-repo dependencies re-enqueued in independent pipelines"
3880
3881 self.gearman_server.hold_jobs_in_queue = True
Evgeny Antyshev0deaaad2015-08-03 20:22:56 +00003882 A = self.fake_gerrit.addFakeChange(project1, 'master', 'A')
3883 B = self.fake_gerrit.addFakeChange(project2, 'master', 'B')
James E. Blair8f78d882015-02-05 08:51:37 -08003884
3885 # A Depends-On: B
3886 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3887 A.subject, B.data['id'])
3888
3889 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3890 self.waitUntilSettled()
3891
3892 self.sched.reconfigure(self.config)
3893
3894 # Make sure the items still share a change queue, and the
3895 # first one is not live.
3896 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 1)
3897 queue = self.sched.layout.pipelines['check'].queues[0]
3898 first_item = queue.queue[0]
3899 for item in queue.queue:
3900 self.assertEqual(item.queue, first_item.queue)
3901 self.assertFalse(first_item.live)
3902 self.assertTrue(queue.queue[1].live)
3903
3904 self.gearman_server.hold_jobs_in_queue = False
3905 self.gearman_server.release()
3906 self.waitUntilSettled()
3907
3908 self.assertEqual(A.data['status'], 'NEW')
3909 self.assertEqual(B.data['status'], 'NEW')
3910 self.assertEqual(A.reported, 1)
3911 self.assertEqual(B.reported, 0)
3912
3913 self.assertEqual(self.history[0].changes, '2,1 1,1')
3914 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 0)
James E. Blair17dd6772015-02-09 14:45:18 -08003915
Evgeny Antyshev0deaaad2015-08-03 20:22:56 +00003916 def test_crd_check_reconfiguration(self):
3917 self._test_crd_check_reconfiguration('org/project1', 'org/project2')
3918
3919 def test_crd_undefined_project(self):
3920 """Test that undefined projects in dependencies are handled for
3921 independent pipelines"""
3922 # It's a hack for fake gerrit,
3923 # as it implies repo creation upon the creation of any change
3924 self.init_repo("org/unknown")
3925 self._test_crd_check_reconfiguration('org/project1', 'org/unknown')
3926
James E. Blair17dd6772015-02-09 14:45:18 -08003927 def test_crd_check_ignore_dependencies(self):
3928 "Test cross-repo dependencies can be ignored"
3929 self.config.set('zuul', 'layout_config',
3930 'tests/fixtures/layout-ignore-dependencies.yaml')
3931 self.sched.reconfigure(self.config)
3932 self.registerJobs()
3933
3934 self.gearman_server.hold_jobs_in_queue = True
3935 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3936 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3937 C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
3938
3939 # A Depends-On: B
3940 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3941 A.subject, B.data['id'])
3942 # C git-depends on B
3943 C.setDependsOn(B, 1)
3944 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3945 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
3946 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
3947 self.waitUntilSettled()
3948
3949 # Make sure none of the items share a change queue, and all
3950 # are live.
3951 check_pipeline = self.sched.layout.pipelines['check']
3952 self.assertEqual(len(check_pipeline.queues), 3)
3953 self.assertEqual(len(check_pipeline.getAllItems()), 3)
3954 for item in check_pipeline.getAllItems():
3955 self.assertTrue(item.live)
3956
3957 self.gearman_server.hold_jobs_in_queue = False
3958 self.gearman_server.release()
3959 self.waitUntilSettled()
3960
3961 self.assertEqual(A.data['status'], 'NEW')
3962 self.assertEqual(B.data['status'], 'NEW')
3963 self.assertEqual(C.data['status'], 'NEW')
3964 self.assertEqual(A.reported, 1)
3965 self.assertEqual(B.reported, 1)
3966 self.assertEqual(C.reported, 1)
3967
3968 # Each job should have tested exactly one change
3969 for job in self.history:
3970 self.assertEqual(len(job.changes.split()), 1)
James E. Blair96698e22015-04-02 07:48:21 -07003971
3972 def test_crd_check_transitive(self):
3973 "Test transitive cross-repo dependencies"
3974 # Specifically, if A -> B -> C, and C gets a new patchset and
3975 # A gets a new patchset, ensure the test of A,2 includes B,1
3976 # and C,2 (not C,1 which would indicate stale data in the
3977 # cache for B).
3978 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3979 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3980 C = self.fake_gerrit.addFakeChange('org/project3', 'master', 'C')
3981
3982 # A Depends-On: B
3983 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3984 A.subject, B.data['id'])
3985
3986 # B Depends-On: C
3987 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3988 B.subject, C.data['id'])
3989
3990 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3991 self.waitUntilSettled()
3992 self.assertEqual(self.history[-1].changes, '3,1 2,1 1,1')
3993
3994 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
3995 self.waitUntilSettled()
3996 self.assertEqual(self.history[-1].changes, '3,1 2,1')
3997
3998 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
3999 self.waitUntilSettled()
4000 self.assertEqual(self.history[-1].changes, '3,1')
4001
4002 C.addPatchset()
4003 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(2))
4004 self.waitUntilSettled()
4005 self.assertEqual(self.history[-1].changes, '3,2')
4006
4007 A.addPatchset()
4008 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
4009 self.waitUntilSettled()
4010 self.assertEqual(self.history[-1].changes, '3,2 2,1 1,2')