blob: a4e47befce518bf4d49b2089a11eb421eeabea6e [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. Blair0e933c52013-07-11 10:18:52 -0700644 def test_trigger_cache(self):
645 "Test that the trigger cache operates correctly"
646 self.worker.hold_jobs_in_build = True
647
648 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
649 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
650 X = self.fake_gerrit.addFakeChange('org/project', 'master', 'X')
651 A.addApproval('CRVW', 2)
652 B.addApproval('CRVW', 2)
653
654 M1 = self.fake_gerrit.addFakeChange('org/project', 'master', 'M1')
655 M1.setMerged()
656
657 B.setDependsOn(A, 1)
658 A.setDependsOn(M1, 1)
659
660 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
661 self.fake_gerrit.addEvent(X.getPatchsetCreatedEvent(1))
662
663 self.waitUntilSettled()
664
665 for build in self.builds:
666 if build.parameters['ZUUL_PIPELINE'] == 'check':
667 build.release()
668 self.waitUntilSettled()
669 for build in self.builds:
670 if build.parameters['ZUUL_PIPELINE'] == 'check':
671 build.release()
672 self.waitUntilSettled()
673
674 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
675 self.waitUntilSettled()
676
Antoine Mussof0506fa2014-06-03 15:03:38 +0200677 self.log.debug("len %s" % self.gerrit._change_cache.keys())
James E. Blair0e933c52013-07-11 10:18:52 -0700678 # there should still be changes in the cache
James E. Blair6c358e72013-07-29 17:06:47 -0700679 self.assertNotEqual(len(self.gerrit._change_cache.keys()), 0)
James E. Blair0e933c52013-07-11 10:18:52 -0700680
681 self.worker.hold_jobs_in_build = False
682 self.worker.release()
683 self.waitUntilSettled()
684
685 self.assertEqual(A.data['status'], 'MERGED')
686 self.assertEqual(B.data['status'], 'MERGED')
687 self.assertEqual(A.queried, 2) # Initial and isMerged
688 self.assertEqual(B.queried, 3) # Initial A, refresh from B, isMerged
689
James E. Blair8c803f82012-07-31 16:25:42 -0700690 def test_can_merge(self):
James E. Blair4886cc12012-07-18 15:39:41 -0700691 "Test whether a change is ready to merge"
James E. Blair8c803f82012-07-31 16:25:42 -0700692 # TODO: move to test_gerrit (this is a unit test!)
693 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
James E. Blairc0dedf82014-08-06 09:37:52 -0700694 source = self.sched.layout.pipelines['gate'].source
695 a = source._getChange(1, 2)
James E. Blaireff88162013-07-01 12:44:14 -0400696 mgr = self.sched.layout.pipelines['gate'].manager
James E. Blairc0dedf82014-08-06 09:37:52 -0700697 self.assertFalse(source.canMerge(a, mgr.getSubmitAllowNeeds()))
James E. Blair8c803f82012-07-31 16:25:42 -0700698
699 A.addApproval('CRVW', 2)
James E. Blairc0dedf82014-08-06 09:37:52 -0700700 a = source._getChange(1, 2, refresh=True)
701 self.assertFalse(source.canMerge(a, mgr.getSubmitAllowNeeds()))
James E. Blair8c803f82012-07-31 16:25:42 -0700702
703 A.addApproval('APRV', 1)
James E. Blairc0dedf82014-08-06 09:37:52 -0700704 a = source._getChange(1, 2, refresh=True)
705 self.assertTrue(source.canMerge(a, mgr.getSubmitAllowNeeds()))
706 source.maintainCache([])
James E. Blair4886cc12012-07-18 15:39:41 -0700707
708 def test_build_configuration(self):
709 "Test that zuul merges the right commits for testing"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700710
711 self.gearman_server.hold_jobs_in_queue = True
James E. Blair4886cc12012-07-18 15:39:41 -0700712 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
713 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
714 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
715 A.addApproval('CRVW', 2)
716 B.addApproval('CRVW', 2)
717 C.addApproval('CRVW', 2)
718 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
719 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
720 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
721 self.waitUntilSettled()
722
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700723 self.gearman_server.release('.*-merge')
James E. Blair4886cc12012-07-18 15:39:41 -0700724 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700725 self.gearman_server.release('.*-merge')
James E. Blair4886cc12012-07-18 15:39:41 -0700726 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700727 self.gearman_server.release('.*-merge')
James E. Blair4886cc12012-07-18 15:39:41 -0700728 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -0700729 queue = self.gearman_server.getQueue()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700730 ref = self.getParameter(queue[-1], 'ZUUL_REF')
731 self.gearman_server.hold_jobs_in_queue = False
732 self.gearman_server.release()
James E. Blair973721f2012-08-15 10:19:43 -0700733 self.waitUntilSettled()
James E. Blair4886cc12012-07-18 15:39:41 -0700734
Monty Taylorbc758832013-06-17 17:22:42 -0400735 path = os.path.join(self.git_root, "org/project")
James E. Blair4886cc12012-07-18 15:39:41 -0700736 repo = git.Repo(path)
737 repo_messages = [c.message.strip() for c in repo.iter_commits(ref)]
738 repo_messages.reverse()
James E. Blair4886cc12012-07-18 15:39:41 -0700739 correct_messages = ['initial commit', 'A-1', 'B-1', 'C-1']
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400740 self.assertEqual(repo_messages, correct_messages)
James E. Blair973721f2012-08-15 10:19:43 -0700741
742 def test_build_configuration_conflict(self):
743 "Test that merge conflicts are handled"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700744
745 self.gearman_server.hold_jobs_in_queue = True
James E. Blair6736beb2013-07-11 15:18:15 -0700746 A = self.fake_gerrit.addFakeChange('org/conflict-project',
747 'master', 'A')
James E. Blair973721f2012-08-15 10:19:43 -0700748 A.addPatchset(['conflict'])
James E. Blair6736beb2013-07-11 15:18:15 -0700749 B = self.fake_gerrit.addFakeChange('org/conflict-project',
750 'master', 'B')
James E. Blair973721f2012-08-15 10:19:43 -0700751 B.addPatchset(['conflict'])
James E. Blair6736beb2013-07-11 15:18:15 -0700752 C = self.fake_gerrit.addFakeChange('org/conflict-project',
753 'master', 'C')
James E. Blair973721f2012-08-15 10:19:43 -0700754 A.addApproval('CRVW', 2)
755 B.addApproval('CRVW', 2)
756 C.addApproval('CRVW', 2)
757 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
758 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
759 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
760 self.waitUntilSettled()
761
James E. Blair6736beb2013-07-11 15:18:15 -0700762 self.assertEqual(A.reported, 1)
763 self.assertEqual(B.reported, 1)
764 self.assertEqual(C.reported, 1)
765
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700766 self.gearman_server.release('.*-merge')
James E. Blair973721f2012-08-15 10:19:43 -0700767 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700768 self.gearman_server.release('.*-merge')
James E. Blair973721f2012-08-15 10:19:43 -0700769 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700770 self.gearman_server.release('.*-merge')
James E. Blair973721f2012-08-15 10:19:43 -0700771 self.waitUntilSettled()
James E. Blair972e3c72013-08-29 12:04:55 -0700772
773 self.assertEqual(len(self.history), 2) # A and C merge jobs
774
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700775 self.gearman_server.hold_jobs_in_queue = False
776 self.gearman_server.release()
James E. Blair973721f2012-08-15 10:19:43 -0700777 self.waitUntilSettled()
778
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400779 self.assertEqual(A.data['status'], 'MERGED')
780 self.assertEqual(B.data['status'], 'NEW')
781 self.assertEqual(C.data['status'], 'MERGED')
782 self.assertEqual(A.reported, 2)
783 self.assertEqual(B.reported, 2)
784 self.assertEqual(C.reported, 2)
James E. Blair972e3c72013-08-29 12:04:55 -0700785 self.assertEqual(len(self.history), 6)
James E. Blair6736beb2013-07-11 15:18:15 -0700786
James E. Blairdaabed22012-08-15 15:38:57 -0700787 def test_post(self):
788 "Test that post jobs run"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700789
Zhongyue Luo5d556072012-09-21 02:00:47 +0900790 e = {
791 "type": "ref-updated",
792 "submitter": {
793 "name": "User Name",
794 },
795 "refUpdate": {
796 "oldRev": "90f173846e3af9154517b88543ffbd1691f31366",
797 "newRev": "d479a0bfcb34da57a31adb2a595c0cf687812543",
798 "refName": "master",
799 "project": "org/project",
800 }
801 }
James E. Blairdaabed22012-08-15 15:38:57 -0700802 self.fake_gerrit.addEvent(e)
803 self.waitUntilSettled()
804
Monty Taylor6bef8ef2013-06-02 08:17:12 -0400805 job_names = [x.name for x in self.history]
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400806 self.assertEqual(len(self.history), 1)
807 self.assertIn('project-post', job_names)
James E. Blairc6294a52012-08-17 10:19:48 -0700808
809 def test_build_configuration_branch(self):
810 "Test that the right commits are on alternate branches"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700811
812 self.gearman_server.hold_jobs_in_queue = True
James E. Blairc6294a52012-08-17 10:19:48 -0700813 A = self.fake_gerrit.addFakeChange('org/project', 'mp', 'A')
814 B = self.fake_gerrit.addFakeChange('org/project', 'mp', 'B')
815 C = self.fake_gerrit.addFakeChange('org/project', 'mp', 'C')
816 A.addApproval('CRVW', 2)
817 B.addApproval('CRVW', 2)
818 C.addApproval('CRVW', 2)
819 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
820 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
821 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
822 self.waitUntilSettled()
823
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700824 self.gearman_server.release('.*-merge')
James E. Blairc6294a52012-08-17 10:19:48 -0700825 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700826 self.gearman_server.release('.*-merge')
James E. Blairc6294a52012-08-17 10:19:48 -0700827 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700828 self.gearman_server.release('.*-merge')
James E. Blairc6294a52012-08-17 10:19:48 -0700829 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -0700830 queue = self.gearman_server.getQueue()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700831 ref = self.getParameter(queue[-1], 'ZUUL_REF')
832 self.gearman_server.hold_jobs_in_queue = False
833 self.gearman_server.release()
James E. Blairc6294a52012-08-17 10:19:48 -0700834 self.waitUntilSettled()
835
Monty Taylorbc758832013-06-17 17:22:42 -0400836 path = os.path.join(self.git_root, "org/project")
James E. Blairc6294a52012-08-17 10:19:48 -0700837 repo = git.Repo(path)
838 repo_messages = [c.message.strip() for c in repo.iter_commits(ref)]
839 repo_messages.reverse()
James E. Blairc6294a52012-08-17 10:19:48 -0700840 correct_messages = ['initial commit', 'mp commit', 'A-1', 'B-1', 'C-1']
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400841 self.assertEqual(repo_messages, correct_messages)
James E. Blairc6294a52012-08-17 10:19:48 -0700842
843 def test_build_configuration_branch_interaction(self):
844 "Test that switching between branches works"
845 self.test_build_configuration()
846 self.test_build_configuration_branch()
847 # C has been merged, undo that
Monty Taylorbc758832013-06-17 17:22:42 -0400848 path = os.path.join(self.upstream_root, "org/project")
James E. Blairc6294a52012-08-17 10:19:48 -0700849 repo = git.Repo(path)
850 repo.heads.master.commit = repo.commit('init')
851 self.test_build_configuration()
852
853 def test_build_configuration_multi_branch(self):
854 "Test that dependent changes on multiple branches are merged"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700855
856 self.gearman_server.hold_jobs_in_queue = True
James E. Blairc6294a52012-08-17 10:19:48 -0700857 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
858 B = self.fake_gerrit.addFakeChange('org/project', 'mp', 'B')
859 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
860 A.addApproval('CRVW', 2)
861 B.addApproval('CRVW', 2)
862 C.addApproval('CRVW', 2)
863 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
864 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
865 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
866 self.waitUntilSettled()
James E. Blairbb1fe502014-03-04 10:15:06 -0800867 queue = self.gearman_server.getQueue()
868 job_A = None
869 for job in queue:
870 if 'project-merge' in job.name:
871 job_A = job
872 ref_A = self.getParameter(job_A, 'ZUUL_REF')
873 commit_A = self.getParameter(job_A, 'ZUUL_COMMIT')
874 self.log.debug("Got Zuul ref for change A: %s" % ref_A)
875 self.log.debug("Got Zuul commit for change A: %s" % commit_A)
James E. Blairc6294a52012-08-17 10:19:48 -0700876
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700877 self.gearman_server.release('.*-merge')
James E. Blairc6294a52012-08-17 10:19:48 -0700878 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -0700879 queue = self.gearman_server.getQueue()
James E. Blaird320d7e2013-07-30 16:36:20 -0700880 job_B = None
881 for job in queue:
882 if 'project-merge' in job.name:
883 job_B = job
884 ref_B = self.getParameter(job_B, 'ZUUL_REF')
James E. Blairbb1fe502014-03-04 10:15:06 -0800885 commit_B = self.getParameter(job_B, 'ZUUL_COMMIT')
James E. Blairf750aa02013-07-15 14:11:24 -0700886 self.log.debug("Got Zuul ref for change B: %s" % ref_B)
James E. Blairbb1fe502014-03-04 10:15:06 -0800887 self.log.debug("Got Zuul commit for change B: %s" % commit_B)
888
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700889 self.gearman_server.release('.*-merge')
James E. Blairc6294a52012-08-17 10:19:48 -0700890 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -0700891 queue = self.gearman_server.getQueue()
James E. Blaird320d7e2013-07-30 16:36:20 -0700892 for job in queue:
893 if 'project-merge' in job.name:
894 job_C = job
895 ref_C = self.getParameter(job_C, 'ZUUL_REF')
James E. Blairbb1fe502014-03-04 10:15:06 -0800896 commit_C = self.getParameter(job_C, 'ZUUL_COMMIT')
James E. Blairf750aa02013-07-15 14:11:24 -0700897 self.log.debug("Got Zuul ref for change C: %s" % ref_C)
James E. Blairbb1fe502014-03-04 10:15:06 -0800898 self.log.debug("Got Zuul commit for change C: %s" % commit_C)
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700899 self.gearman_server.hold_jobs_in_queue = False
900 self.gearman_server.release()
James E. Blairc6294a52012-08-17 10:19:48 -0700901 self.waitUntilSettled()
902
Monty Taylorbc758832013-06-17 17:22:42 -0400903 path = os.path.join(self.git_root, "org/project")
James E. Blairc6294a52012-08-17 10:19:48 -0700904 repo = git.Repo(path)
905
906 repo_messages = [c.message.strip()
James E. Blairf750aa02013-07-15 14:11:24 -0700907 for c in repo.iter_commits(ref_C)]
James E. Blairbb1fe502014-03-04 10:15:06 -0800908 repo_shas = [c.hexsha for c in repo.iter_commits(ref_C)]
James E. Blairc6294a52012-08-17 10:19:48 -0700909 repo_messages.reverse()
James E. Blairc6294a52012-08-17 10:19:48 -0700910 correct_messages = ['initial commit', 'A-1', 'C-1']
James E. Blairbb1fe502014-03-04 10:15:06 -0800911 # Ensure the right commits are in the history for this ref
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400912 self.assertEqual(repo_messages, correct_messages)
James E. Blairbb1fe502014-03-04 10:15:06 -0800913 # Ensure ZUUL_REF -> ZUUL_COMMIT
914 self.assertEqual(repo_shas[0], commit_C)
James E. Blairc6294a52012-08-17 10:19:48 -0700915
916 repo_messages = [c.message.strip()
James E. Blairf750aa02013-07-15 14:11:24 -0700917 for c in repo.iter_commits(ref_B)]
James E. Blairbb1fe502014-03-04 10:15:06 -0800918 repo_shas = [c.hexsha for c in repo.iter_commits(ref_B)]
James E. Blairc6294a52012-08-17 10:19:48 -0700919 repo_messages.reverse()
James E. Blairc6294a52012-08-17 10:19:48 -0700920 correct_messages = ['initial commit', 'mp commit', 'B-1']
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400921 self.assertEqual(repo_messages, correct_messages)
James E. Blairbb1fe502014-03-04 10:15:06 -0800922 self.assertEqual(repo_shas[0], commit_B)
923
924 repo_messages = [c.message.strip()
925 for c in repo.iter_commits(ref_A)]
926 repo_shas = [c.hexsha for c in repo.iter_commits(ref_A)]
927 repo_messages.reverse()
928 correct_messages = ['initial commit', 'A-1']
929 self.assertEqual(repo_messages, correct_messages)
930 self.assertEqual(repo_shas[0], commit_A)
931
932 self.assertNotEqual(ref_A, ref_B, ref_C)
933 self.assertNotEqual(commit_A, commit_B, commit_C)
James E. Blair7f71c802012-08-22 13:04:32 -0700934
935 def test_one_job_project(self):
936 "Test that queueing works with one job"
937 A = self.fake_gerrit.addFakeChange('org/one-job-project',
938 'master', 'A')
939 B = self.fake_gerrit.addFakeChange('org/one-job-project',
940 'master', 'B')
941 A.addApproval('CRVW', 2)
942 B.addApproval('CRVW', 2)
943 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
944 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
945 self.waitUntilSettled()
946
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400947 self.assertEqual(A.data['status'], 'MERGED')
948 self.assertEqual(A.reported, 2)
949 self.assertEqual(B.data['status'], 'MERGED')
950 self.assertEqual(B.reported, 2)
James E. Blaircaec0c52012-08-22 14:52:22 -0700951
Antoine Musso80edd5a2013-02-13 15:37:53 +0100952 def test_job_from_templates_launched(self):
953 "Test whether a job generated via a template can be launched"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700954
Antoine Musso80edd5a2013-02-13 15:37:53 +0100955 A = self.fake_gerrit.addFakeChange(
956 'org/templated-project', 'master', 'A')
957 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
958 self.waitUntilSettled()
Antoine Musso80edd5a2013-02-13 15:37:53 +0100959
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400960 self.assertEqual(self.getJobFromHistory('project-test1').result,
961 'SUCCESS')
962 self.assertEqual(self.getJobFromHistory('project-test2').result,
963 'SUCCESS')
Antoine Musso80edd5a2013-02-13 15:37:53 +0100964
James E. Blair3e98c022013-12-16 15:25:38 -0800965 def test_layered_templates(self):
966 "Test whether a job generated via a template can be launched"
967
968 A = self.fake_gerrit.addFakeChange(
969 'org/layered-project', 'master', 'A')
970 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
971 self.waitUntilSettled()
972
973 self.assertEqual(self.getJobFromHistory('project-test1').result,
974 'SUCCESS')
975 self.assertEqual(self.getJobFromHistory('project-test2').result,
976 'SUCCESS')
James E. Blairaea6cf62013-12-16 15:38:12 -0800977 self.assertEqual(self.getJobFromHistory('layered-project-test3'
978 ).result, 'SUCCESS')
979 self.assertEqual(self.getJobFromHistory('layered-project-test4'
980 ).result, 'SUCCESS')
James E. Blair12a92b12014-03-26 11:54:53 -0700981 self.assertEqual(self.getJobFromHistory('layered-project-foo-test5'
982 ).result, 'SUCCESS')
James E. Blair3e98c022013-12-16 15:25:38 -0800983 self.assertEqual(self.getJobFromHistory('project-test6').result,
984 'SUCCESS')
985
James E. Blaircaec0c52012-08-22 14:52:22 -0700986 def test_dependent_changes_dequeue(self):
987 "Test that dependent patches are not needlessly tested"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700988
James E. Blaircaec0c52012-08-22 14:52:22 -0700989 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
990 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
991 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
992 A.addApproval('CRVW', 2)
993 B.addApproval('CRVW', 2)
994 C.addApproval('CRVW', 2)
995
996 M1 = self.fake_gerrit.addFakeChange('org/project', 'master', 'M1')
997 M1.setMerged()
998
999 # C -> B -> A -> M1
1000
1001 C.setDependsOn(B, 1)
1002 B.setDependsOn(A, 1)
1003 A.setDependsOn(M1, 1)
1004
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001005 self.worker.addFailTest('project-merge', A)
James E. Blaircaec0c52012-08-22 14:52:22 -07001006
1007 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1008 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1009 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1010
1011 self.waitUntilSettled()
1012
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001013 self.assertEqual(A.data['status'], 'NEW')
1014 self.assertEqual(A.reported, 2)
1015 self.assertEqual(B.data['status'], 'NEW')
1016 self.assertEqual(B.reported, 2)
1017 self.assertEqual(C.data['status'], 'NEW')
1018 self.assertEqual(C.reported, 2)
1019 self.assertEqual(len(self.history), 1)
James E. Blairec590122012-08-22 15:19:31 -07001020
James E. Blair972e3c72013-08-29 12:04:55 -07001021 def test_failing_dependent_changes(self):
1022 "Test that failing dependent patches are taken out of stream"
1023 self.worker.hold_jobs_in_build = True
1024 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1025 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1026 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1027 D = self.fake_gerrit.addFakeChange('org/project', 'master', 'D')
1028 E = self.fake_gerrit.addFakeChange('org/project', 'master', 'E')
1029 A.addApproval('CRVW', 2)
1030 B.addApproval('CRVW', 2)
1031 C.addApproval('CRVW', 2)
1032 D.addApproval('CRVW', 2)
1033 E.addApproval('CRVW', 2)
1034
1035 # E, D -> C -> B, A
1036
1037 D.setDependsOn(C, 1)
1038 C.setDependsOn(B, 1)
1039
1040 self.worker.addFailTest('project-test1', B)
1041
1042 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1043 self.fake_gerrit.addEvent(D.addApproval('APRV', 1))
1044 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1045 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1046 self.fake_gerrit.addEvent(E.addApproval('APRV', 1))
1047
1048 self.waitUntilSettled()
1049 self.worker.release('.*-merge')
1050 self.waitUntilSettled()
1051 self.worker.release('.*-merge')
1052 self.waitUntilSettled()
1053 self.worker.release('.*-merge')
1054 self.waitUntilSettled()
1055 self.worker.release('.*-merge')
1056 self.waitUntilSettled()
1057 self.worker.release('.*-merge')
1058 self.waitUntilSettled()
1059
1060 self.worker.hold_jobs_in_build = False
1061 for build in self.builds:
1062 if build.parameters['ZUUL_CHANGE'] != '1':
1063 build.release()
1064 self.waitUntilSettled()
1065
1066 self.worker.release()
1067 self.waitUntilSettled()
1068
1069 self.assertEqual(A.data['status'], 'MERGED')
1070 self.assertEqual(A.reported, 2)
Jeremy Stanley10837132014-08-02 16:10:56 +00001071 self.assertIn('Build succeeded', A.messages[1])
James E. Blair972e3c72013-08-29 12:04:55 -07001072 self.assertEqual(B.data['status'], 'NEW')
1073 self.assertEqual(B.reported, 2)
Jeremy Stanley10837132014-08-02 16:10:56 +00001074 self.assertIn('Build failed', B.messages[1])
James E. Blair972e3c72013-08-29 12:04:55 -07001075 self.assertEqual(C.data['status'], 'NEW')
1076 self.assertEqual(C.reported, 2)
Jeremy Stanley10837132014-08-02 16:10:56 +00001077 self.assertIn('depends on a change', C.messages[1])
James E. Blair972e3c72013-08-29 12:04:55 -07001078 self.assertEqual(D.data['status'], 'NEW')
1079 self.assertEqual(D.reported, 2)
Jeremy Stanley10837132014-08-02 16:10:56 +00001080 self.assertIn('depends on a change', D.messages[1])
James E. Blair972e3c72013-08-29 12:04:55 -07001081 self.assertEqual(E.data['status'], 'MERGED')
1082 self.assertEqual(E.reported, 2)
Jeremy Stanley10837132014-08-02 16:10:56 +00001083 self.assertIn('Build succeeded', E.messages[1])
James E. Blair972e3c72013-08-29 12:04:55 -07001084 self.assertEqual(len(self.history), 18)
1085
James E. Blairec590122012-08-22 15:19:31 -07001086 def test_head_is_dequeued_once(self):
James E. Blair2fa50962013-01-30 21:50:41 -08001087 "Test that if a change at the head fails it is dequeued only once"
James E. Blairec590122012-08-22 15:19:31 -07001088 # If it's dequeued more than once, we should see extra
1089 # aborted jobs.
James E. Blairec590122012-08-22 15:19:31 -07001090
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001091 self.worker.hold_jobs_in_build = True
James E. Blairec590122012-08-22 15:19:31 -07001092 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
1093 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
1094 C = self.fake_gerrit.addFakeChange('org/project1', 'master', 'C')
1095 A.addApproval('CRVW', 2)
1096 B.addApproval('CRVW', 2)
1097 C.addApproval('CRVW', 2)
1098
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001099 self.worker.addFailTest('project1-test1', A)
1100 self.worker.addFailTest('project1-test2', A)
1101 self.worker.addFailTest('project1-project2-integration', A)
James E. Blairec590122012-08-22 15:19:31 -07001102
1103 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1104 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1105 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1106
1107 self.waitUntilSettled()
James E. Blairec590122012-08-22 15:19:31 -07001108
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001109 self.assertEqual(len(self.builds), 1)
1110 self.assertEqual(self.builds[0].name, 'project1-merge')
1111 self.assertTrue(self.job_has_changes(self.builds[0], A))
James E. Blairec590122012-08-22 15:19:31 -07001112
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001113 self.worker.release('.*-merge')
James E. Blairec590122012-08-22 15:19:31 -07001114 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001115 self.worker.release('.*-merge')
James E. Blairec590122012-08-22 15:19:31 -07001116 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001117 self.worker.release('.*-merge')
James E. Blairec590122012-08-22 15:19:31 -07001118 self.waitUntilSettled()
1119
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001120 self.assertEqual(len(self.builds), 9)
1121 self.assertEqual(self.builds[0].name, 'project1-test1')
1122 self.assertEqual(self.builds[1].name, 'project1-test2')
1123 self.assertEqual(self.builds[2].name, 'project1-project2-integration')
1124 self.assertEqual(self.builds[3].name, 'project1-test1')
1125 self.assertEqual(self.builds[4].name, 'project1-test2')
1126 self.assertEqual(self.builds[5].name, 'project1-project2-integration')
1127 self.assertEqual(self.builds[6].name, 'project1-test1')
1128 self.assertEqual(self.builds[7].name, 'project1-test2')
1129 self.assertEqual(self.builds[8].name, 'project1-project2-integration')
James E. Blairec590122012-08-22 15:19:31 -07001130
Monty Taylor6bef8ef2013-06-02 08:17:12 -04001131 self.release(self.builds[0])
James E. Blairec590122012-08-22 15:19:31 -07001132 self.waitUntilSettled()
1133
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001134 self.assertEqual(len(self.builds), 3) # test2,integration, merge for B
1135 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 6)
James E. Blairec590122012-08-22 15:19:31 -07001136
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001137 self.worker.hold_jobs_in_build = False
1138 self.worker.release()
James E. Blairec590122012-08-22 15:19:31 -07001139 self.waitUntilSettled()
1140
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001141 self.assertEqual(len(self.builds), 0)
1142 self.assertEqual(len(self.history), 20)
James E. Blaircaec0c52012-08-22 14:52:22 -07001143
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001144 self.assertEqual(A.data['status'], 'NEW')
1145 self.assertEqual(B.data['status'], 'MERGED')
1146 self.assertEqual(C.data['status'], 'MERGED')
1147 self.assertEqual(A.reported, 2)
1148 self.assertEqual(B.reported, 2)
1149 self.assertEqual(C.reported, 2)
James E. Blair4ec821f2012-08-23 15:28:28 -07001150
1151 def test_nonvoting_job(self):
1152 "Test that non-voting jobs don't vote."
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001153
James E. Blair4ec821f2012-08-23 15:28:28 -07001154 A = self.fake_gerrit.addFakeChange('org/nonvoting-project',
1155 'master', 'A')
1156 A.addApproval('CRVW', 2)
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001157 self.worker.addFailTest('nonvoting-project-test2', A)
James E. Blair4ec821f2012-08-23 15:28:28 -07001158 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1159
1160 self.waitUntilSettled()
James E. Blair4ec821f2012-08-23 15:28:28 -07001161
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001162 self.assertEqual(A.data['status'], 'MERGED')
1163 self.assertEqual(A.reported, 2)
1164 self.assertEqual(
1165 self.getJobFromHistory('nonvoting-project-merge').result,
1166 'SUCCESS')
1167 self.assertEqual(
1168 self.getJobFromHistory('nonvoting-project-test1').result,
1169 'SUCCESS')
1170 self.assertEqual(
1171 self.getJobFromHistory('nonvoting-project-test2').result,
1172 'FAILURE')
James E. Blaire0487072012-08-29 17:38:31 -07001173
1174 def test_check_queue_success(self):
1175 "Test successful check queue jobs."
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001176
James E. Blaire0487072012-08-29 17:38:31 -07001177 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1178 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1179
1180 self.waitUntilSettled()
James E. Blaire0487072012-08-29 17:38:31 -07001181
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001182 self.assertEqual(A.data['status'], 'NEW')
1183 self.assertEqual(A.reported, 1)
1184 self.assertEqual(self.getJobFromHistory('project-merge').result,
1185 'SUCCESS')
1186 self.assertEqual(self.getJobFromHistory('project-test1').result,
1187 'SUCCESS')
1188 self.assertEqual(self.getJobFromHistory('project-test2').result,
1189 'SUCCESS')
James E. Blaire0487072012-08-29 17:38:31 -07001190
1191 def test_check_queue_failure(self):
1192 "Test failed check queue jobs."
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001193
James E. Blaire0487072012-08-29 17:38:31 -07001194 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001195 self.worker.addFailTest('project-test2', A)
James E. Blaire0487072012-08-29 17:38:31 -07001196 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1197
1198 self.waitUntilSettled()
James E. Blaire0487072012-08-29 17:38:31 -07001199
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001200 self.assertEqual(A.data['status'], 'NEW')
1201 self.assertEqual(A.reported, 1)
1202 self.assertEqual(self.getJobFromHistory('project-merge').result,
James E. Blair78e31b32013-07-09 09:11:34 -07001203 'SUCCESS')
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001204 self.assertEqual(self.getJobFromHistory('project-test1').result,
1205 'SUCCESS')
1206 self.assertEqual(self.getJobFromHistory('project-test2').result,
1207 'FAILURE')
James E. Blair127bc182012-08-28 15:55:15 -07001208
1209 def test_dependent_behind_dequeue(self):
1210 "test that dependent changes behind dequeued changes work"
1211 # This complicated test is a reproduction of a real life bug
1212 self.sched.reconfigure(self.config)
James E. Blair127bc182012-08-28 15:55:15 -07001213
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001214 self.worker.hold_jobs_in_build = True
James E. Blair127bc182012-08-28 15:55:15 -07001215 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
1216 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
1217 C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
1218 D = self.fake_gerrit.addFakeChange('org/project2', 'master', 'D')
1219 E = self.fake_gerrit.addFakeChange('org/project2', 'master', 'E')
1220 F = self.fake_gerrit.addFakeChange('org/project3', 'master', 'F')
1221 D.setDependsOn(C, 1)
1222 E.setDependsOn(D, 1)
1223 A.addApproval('CRVW', 2)
1224 B.addApproval('CRVW', 2)
1225 C.addApproval('CRVW', 2)
1226 D.addApproval('CRVW', 2)
1227 E.addApproval('CRVW', 2)
1228 F.addApproval('CRVW', 2)
1229
1230 A.fail_merge = True
James E. Blair127bc182012-08-28 15:55:15 -07001231
1232 # Change object re-use in the gerrit trigger is hidden if
1233 # changes are added in quick succession; waiting makes it more
1234 # like real life.
1235 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1236 self.waitUntilSettled()
1237 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1238 self.waitUntilSettled()
1239
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001240 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001241 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001242 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001243 self.waitUntilSettled()
1244
1245 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1246 self.waitUntilSettled()
1247 self.fake_gerrit.addEvent(D.addApproval('APRV', 1))
1248 self.waitUntilSettled()
1249 self.fake_gerrit.addEvent(E.addApproval('APRV', 1))
1250 self.waitUntilSettled()
1251 self.fake_gerrit.addEvent(F.addApproval('APRV', 1))
1252 self.waitUntilSettled()
1253
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001254 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001255 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001256 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001257 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001258 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001259 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001260 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001261 self.waitUntilSettled()
1262
1263 # all jobs running
James E. Blaire955e062012-10-08 09:49:03 -07001264
1265 # Grab pointers to the jobs we want to release before
1266 # releasing any, because list indexes may change as
1267 # the jobs complete.
Monty Taylor6bef8ef2013-06-02 08:17:12 -04001268 a, b, c = self.builds[:3]
James E. Blaire955e062012-10-08 09:49:03 -07001269 a.release()
1270 b.release()
1271 c.release()
James E. Blair127bc182012-08-28 15:55:15 -07001272 self.waitUntilSettled()
1273
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001274 self.worker.hold_jobs_in_build = False
1275 self.worker.release()
James E. Blair127bc182012-08-28 15:55:15 -07001276 self.waitUntilSettled()
1277
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001278 self.assertEqual(A.data['status'], 'NEW')
1279 self.assertEqual(B.data['status'], 'MERGED')
1280 self.assertEqual(C.data['status'], 'MERGED')
1281 self.assertEqual(D.data['status'], 'MERGED')
1282 self.assertEqual(E.data['status'], 'MERGED')
1283 self.assertEqual(F.data['status'], 'MERGED')
James E. Blair127bc182012-08-28 15:55:15 -07001284
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001285 self.assertEqual(A.reported, 2)
1286 self.assertEqual(B.reported, 2)
1287 self.assertEqual(C.reported, 2)
1288 self.assertEqual(D.reported, 2)
1289 self.assertEqual(E.reported, 2)
1290 self.assertEqual(F.reported, 2)
James E. Blair127bc182012-08-28 15:55:15 -07001291
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001292 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 15)
1293 self.assertEqual(len(self.history), 44)
James E. Blair05fed602012-09-07 12:45:24 -07001294
1295 def test_merger_repack(self):
1296 "Test that the merger works after a repack"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001297
James E. Blair05fed602012-09-07 12:45:24 -07001298 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1299 A.addApproval('CRVW', 2)
1300 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1301 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001302 self.assertEqual(self.getJobFromHistory('project-merge').result,
1303 'SUCCESS')
1304 self.assertEqual(self.getJobFromHistory('project-test1').result,
1305 'SUCCESS')
1306 self.assertEqual(self.getJobFromHistory('project-test2').result,
1307 'SUCCESS')
1308 self.assertEqual(A.data['status'], 'MERGED')
1309 self.assertEqual(A.reported, 2)
James E. Blair05fed602012-09-07 12:45:24 -07001310 self.assertEmptyQueues()
James E. Blair4ca985f2013-05-30 12:27:43 -07001311 self.worker.build_history = []
James E. Blair05fed602012-09-07 12:45:24 -07001312
Monty Taylorbc758832013-06-17 17:22:42 -04001313 path = os.path.join(self.git_root, "org/project")
1314 print repack_repo(path)
James E. Blair05fed602012-09-07 12:45:24 -07001315
1316 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1317 A.addApproval('CRVW', 2)
1318 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1319 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001320 self.assertEqual(self.getJobFromHistory('project-merge').result,
1321 'SUCCESS')
1322 self.assertEqual(self.getJobFromHistory('project-test1').result,
1323 'SUCCESS')
1324 self.assertEqual(self.getJobFromHistory('project-test2').result,
1325 'SUCCESS')
1326 self.assertEqual(A.data['status'], 'MERGED')
1327 self.assertEqual(A.reported, 2)
James E. Blair7ee88a22012-09-12 18:59:31 +02001328
James E. Blair4886f282012-11-15 09:27:33 -08001329 def test_merger_repack_large_change(self):
1330 "Test that the merger works with large changes after a repack"
1331 # https://bugs.launchpad.net/zuul/+bug/1078946
James E. Blairac2c3242014-01-24 13:38:51 -08001332 # This test assumes the repo is already cloned; make sure it is
1333 url = self.sched.triggers['gerrit'].getGitUrl(
1334 self.sched.layout.projects['org/project1'])
James E. Blair4076e2b2014-01-28 12:42:20 -08001335 self.merge_server.merger.addProject('org/project1', url)
James E. Blair4886f282012-11-15 09:27:33 -08001336 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
1337 A.addPatchset(large=True)
Monty Taylorbc758832013-06-17 17:22:42 -04001338 path = os.path.join(self.upstream_root, "org/project1")
1339 print repack_repo(path)
1340 path = os.path.join(self.git_root, "org/project1")
1341 print repack_repo(path)
James E. Blair4886f282012-11-15 09:27:33 -08001342
1343 A.addApproval('CRVW', 2)
1344 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1345 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001346 self.assertEqual(self.getJobFromHistory('project1-merge').result,
1347 'SUCCESS')
1348 self.assertEqual(self.getJobFromHistory('project1-test1').result,
1349 'SUCCESS')
1350 self.assertEqual(self.getJobFromHistory('project1-test2').result,
1351 'SUCCESS')
1352 self.assertEqual(A.data['status'], 'MERGED')
1353 self.assertEqual(A.reported, 2)
James E. Blair4886f282012-11-15 09:27:33 -08001354
James E. Blair7ee88a22012-09-12 18:59:31 +02001355 def test_nonexistent_job(self):
1356 "Test launching a job that doesn't exist"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001357 # Set to the state immediately after a restart
1358 self.resetGearmanServer()
1359 self.launcher.negative_function_cache_ttl = 0
James E. Blair7ee88a22012-09-12 18:59:31 +02001360
1361 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1362 A.addApproval('CRVW', 2)
1363 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1364 # There may be a thread about to report a lost change
1365 while A.reported < 2:
1366 self.waitUntilSettled()
Monty Taylor6bef8ef2013-06-02 08:17:12 -04001367 job_names = [x.name for x in self.history]
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001368 self.assertFalse(job_names)
1369 self.assertEqual(A.data['status'], 'NEW')
1370 self.assertEqual(A.reported, 2)
James E. Blair7ee88a22012-09-12 18:59:31 +02001371 self.assertEmptyQueues()
1372
1373 # Make sure things still work:
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001374 self.registerJobs()
James E. Blair7ee88a22012-09-12 18:59:31 +02001375 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1376 A.addApproval('CRVW', 2)
1377 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1378 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001379 self.assertEqual(self.getJobFromHistory('project-merge').result,
1380 'SUCCESS')
1381 self.assertEqual(self.getJobFromHistory('project-test1').result,
1382 'SUCCESS')
1383 self.assertEqual(self.getJobFromHistory('project-test2').result,
1384 'SUCCESS')
1385 self.assertEqual(A.data['status'], 'MERGED')
1386 self.assertEqual(A.reported, 2)
James E. Blairf62d4282012-12-31 17:01:50 -08001387
1388 def test_single_nonexistent_post_job(self):
1389 "Test launching a single post job that doesn't exist"
James E. Blairf62d4282012-12-31 17:01:50 -08001390 e = {
1391 "type": "ref-updated",
1392 "submitter": {
1393 "name": "User Name",
1394 },
1395 "refUpdate": {
1396 "oldRev": "90f173846e3af9154517b88543ffbd1691f31366",
1397 "newRev": "d479a0bfcb34da57a31adb2a595c0cf687812543",
1398 "refName": "master",
1399 "project": "org/project",
1400 }
1401 }
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001402 # Set to the state immediately after a restart
1403 self.resetGearmanServer()
1404 self.launcher.negative_function_cache_ttl = 0
1405
James E. Blairf62d4282012-12-31 17:01:50 -08001406 self.fake_gerrit.addEvent(e)
1407 self.waitUntilSettled()
1408
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001409 self.assertEqual(len(self.history), 0)
James E. Blair2fa50962013-01-30 21:50:41 -08001410
1411 def test_new_patchset_dequeues_old(self):
1412 "Test that a new patchset causes the old to be dequeued"
1413 # D -> C (depends on B) -> B (depends on A) -> A -> M
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001414 self.worker.hold_jobs_in_build = True
James E. Blair2fa50962013-01-30 21:50:41 -08001415 M = self.fake_gerrit.addFakeChange('org/project', 'master', 'M')
1416 M.setMerged()
1417
1418 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1419 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1420 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1421 D = self.fake_gerrit.addFakeChange('org/project', 'master', 'D')
1422 A.addApproval('CRVW', 2)
1423 B.addApproval('CRVW', 2)
1424 C.addApproval('CRVW', 2)
1425 D.addApproval('CRVW', 2)
1426
1427 C.setDependsOn(B, 1)
1428 B.setDependsOn(A, 1)
1429 A.setDependsOn(M, 1)
1430
1431 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1432 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1433 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1434 self.fake_gerrit.addEvent(D.addApproval('APRV', 1))
1435 self.waitUntilSettled()
1436
1437 B.addPatchset()
1438 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(2))
1439 self.waitUntilSettled()
1440
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001441 self.worker.hold_jobs_in_build = False
1442 self.worker.release()
James E. Blair2fa50962013-01-30 21:50:41 -08001443 self.waitUntilSettled()
1444
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001445 self.assertEqual(A.data['status'], 'MERGED')
1446 self.assertEqual(A.reported, 2)
1447 self.assertEqual(B.data['status'], 'NEW')
1448 self.assertEqual(B.reported, 2)
1449 self.assertEqual(C.data['status'], 'NEW')
1450 self.assertEqual(C.reported, 2)
1451 self.assertEqual(D.data['status'], 'MERGED')
1452 self.assertEqual(D.reported, 2)
1453 self.assertEqual(len(self.history), 9) # 3 each for A, B, D.
James E. Blair2fa50962013-01-30 21:50:41 -08001454
Antoine Mussobd86a312014-01-08 14:51:33 +01001455 def test_abandoned_change_dequeues(self):
1456 "Test that an abandoned change is dequeued"
1457
1458 self.worker.hold_jobs_in_build = True
1459
1460 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1461 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1462 self.waitUntilSettled()
1463 self.assertEqual(len(self.builds), 1, "One job being built (on hold)")
1464 self.assertEqual(self.builds[0].name, 'project-merge')
1465
1466 self.fake_gerrit.addEvent(A.getChangeAbandonedEvent())
1467 self.waitUntilSettled()
1468
1469 # For debugging purposes...
Joshua Hesketh29d99b72014-08-19 16:27:42 +10001470 # for pipeline in self.sched.layout.pipelines.values():
1471 # for queue in pipeline.queues:
1472 # self.log.info("pipepline %s queue %s contents %s" % (
1473 # pipeline.name, queue.name, queue.queue))
Antoine Mussobd86a312014-01-08 14:51:33 +01001474
1475 self.worker.release('.*-merge')
1476 self.waitUntilSettled()
1477
1478 self.assertEqual(len(self.builds), 0, "No job running")
1479 self.assertEmptyQueues()
1480 self.assertEqual(len(self.history), 1, "Only one build in history")
1481 self.assertEqual(self.history[0].result, 'ABORTED',
1482 'Build should have been aborted')
1483 self.assertEqual(A.reported, 0, "Abandoned change should not report")
1484
Arx Cruzb1b010d2013-10-28 19:49:59 -02001485 def test_zuul_url_return(self):
1486 "Test if ZUUL_URL is returning when zuul_url is set in zuul.conf"
James E. Blair4076e2b2014-01-28 12:42:20 -08001487 self.assertTrue(self.sched.config.has_option('merger', 'zuul_url'))
Arx Cruzb1b010d2013-10-28 19:49:59 -02001488 self.worker.hold_jobs_in_build = True
1489
1490 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1491 A.addApproval('CRVW', 2)
1492 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1493 self.waitUntilSettled()
1494
1495 self.assertEqual(len(self.builds), 1)
1496 for build in self.builds:
1497 self.assertTrue('ZUUL_URL' in build.parameters)
1498
1499 self.worker.hold_jobs_in_build = False
1500 self.worker.release()
1501 self.waitUntilSettled()
1502
James E. Blair2fa50962013-01-30 21:50:41 -08001503 def test_new_patchset_dequeues_old_on_head(self):
1504 "Test that a new patchset causes the old to be dequeued (at head)"
1505 # D -> C (depends on B) -> B (depends on A) -> A -> M
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001506 self.worker.hold_jobs_in_build = True
James E. Blair2fa50962013-01-30 21:50:41 -08001507 M = self.fake_gerrit.addFakeChange('org/project', 'master', 'M')
1508 M.setMerged()
1509 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1510 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1511 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1512 D = self.fake_gerrit.addFakeChange('org/project', 'master', 'D')
1513 A.addApproval('CRVW', 2)
1514 B.addApproval('CRVW', 2)
1515 C.addApproval('CRVW', 2)
1516 D.addApproval('CRVW', 2)
1517
1518 C.setDependsOn(B, 1)
1519 B.setDependsOn(A, 1)
1520 A.setDependsOn(M, 1)
1521
1522 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1523 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1524 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1525 self.fake_gerrit.addEvent(D.addApproval('APRV', 1))
1526 self.waitUntilSettled()
1527
1528 A.addPatchset()
1529 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
1530 self.waitUntilSettled()
1531
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001532 self.worker.hold_jobs_in_build = False
1533 self.worker.release()
James E. Blair2fa50962013-01-30 21:50:41 -08001534 self.waitUntilSettled()
1535
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001536 self.assertEqual(A.data['status'], 'NEW')
1537 self.assertEqual(A.reported, 2)
1538 self.assertEqual(B.data['status'], 'NEW')
1539 self.assertEqual(B.reported, 2)
1540 self.assertEqual(C.data['status'], 'NEW')
1541 self.assertEqual(C.reported, 2)
1542 self.assertEqual(D.data['status'], 'MERGED')
1543 self.assertEqual(D.reported, 2)
1544 self.assertEqual(len(self.history), 7)
James E. Blair2fa50962013-01-30 21:50:41 -08001545
1546 def test_new_patchset_dequeues_old_without_dependents(self):
1547 "Test that a new patchset causes only the old to be dequeued"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001548 self.worker.hold_jobs_in_build = True
James E. Blair2fa50962013-01-30 21:50:41 -08001549 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1550 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1551 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1552 A.addApproval('CRVW', 2)
1553 B.addApproval('CRVW', 2)
1554 C.addApproval('CRVW', 2)
1555
1556 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1557 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1558 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1559 self.waitUntilSettled()
1560
1561 B.addPatchset()
1562 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(2))
1563 self.waitUntilSettled()
1564
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001565 self.worker.hold_jobs_in_build = False
1566 self.worker.release()
James E. Blair2fa50962013-01-30 21:50:41 -08001567 self.waitUntilSettled()
1568
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001569 self.assertEqual(A.data['status'], 'MERGED')
1570 self.assertEqual(A.reported, 2)
1571 self.assertEqual(B.data['status'], 'NEW')
1572 self.assertEqual(B.reported, 2)
1573 self.assertEqual(C.data['status'], 'MERGED')
1574 self.assertEqual(C.reported, 2)
1575 self.assertEqual(len(self.history), 9)
James E. Blair2fa50962013-01-30 21:50:41 -08001576
1577 def test_new_patchset_dequeues_old_independent_queue(self):
1578 "Test that a new patchset causes the old to be dequeued (independent)"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001579 self.worker.hold_jobs_in_build = True
James E. Blair2fa50962013-01-30 21:50:41 -08001580 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1581 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1582 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1583 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1584 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1585 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
1586 self.waitUntilSettled()
1587
1588 B.addPatchset()
1589 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(2))
1590 self.waitUntilSettled()
1591
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001592 self.worker.hold_jobs_in_build = False
1593 self.worker.release()
James E. Blair2fa50962013-01-30 21:50:41 -08001594 self.waitUntilSettled()
1595
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001596 self.assertEqual(A.data['status'], 'NEW')
1597 self.assertEqual(A.reported, 1)
1598 self.assertEqual(B.data['status'], 'NEW')
1599 self.assertEqual(B.reported, 1)
1600 self.assertEqual(C.data['status'], 'NEW')
1601 self.assertEqual(C.reported, 1)
1602 self.assertEqual(len(self.history), 10)
1603 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 1)
James E. Blair7d0dedc2013-02-21 17:26:09 -08001604
James E. Blair18c64442014-03-18 10:14:45 -07001605 def test_noop_job(self):
1606 "Test that the internal noop job works"
1607 A = self.fake_gerrit.addFakeChange('org/noop-project', 'master', 'A')
1608 A.addApproval('CRVW', 2)
1609 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1610 self.waitUntilSettled()
1611
1612 self.assertEqual(len(self.gearman_server.getQueue()), 0)
1613 self.assertTrue(self.sched._areAllBuildsComplete())
1614 self.assertEqual(len(self.history), 0)
1615 self.assertEqual(A.data['status'], 'MERGED')
1616 self.assertEqual(A.reported, 2)
1617
James E. Blair7d0dedc2013-02-21 17:26:09 -08001618 def test_zuul_refs(self):
1619 "Test that zuul refs exist and have the right changes"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001620 self.worker.hold_jobs_in_build = True
James E. Blair7d0dedc2013-02-21 17:26:09 -08001621 M1 = self.fake_gerrit.addFakeChange('org/project1', 'master', 'M1')
1622 M1.setMerged()
1623 M2 = self.fake_gerrit.addFakeChange('org/project2', 'master', 'M2')
1624 M2.setMerged()
1625
1626 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
1627 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
1628 C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
1629 D = self.fake_gerrit.addFakeChange('org/project2', 'master', 'D')
1630 A.addApproval('CRVW', 2)
1631 B.addApproval('CRVW', 2)
1632 C.addApproval('CRVW', 2)
1633 D.addApproval('CRVW', 2)
1634 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1635 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1636 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1637 self.fake_gerrit.addEvent(D.addApproval('APRV', 1))
1638
1639 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001640 self.worker.release('.*-merge')
James E. Blair7d0dedc2013-02-21 17:26:09 -08001641 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001642 self.worker.release('.*-merge')
James E. Blair7d0dedc2013-02-21 17:26:09 -08001643 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001644 self.worker.release('.*-merge')
James E. Blair7d0dedc2013-02-21 17:26:09 -08001645 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001646 self.worker.release('.*-merge')
James E. Blair7d0dedc2013-02-21 17:26:09 -08001647 self.waitUntilSettled()
1648
James E. Blair7d0dedc2013-02-21 17:26:09 -08001649 a_zref = b_zref = c_zref = d_zref = None
Monty Taylor6bef8ef2013-06-02 08:17:12 -04001650 for x in self.builds:
James E. Blair7d0dedc2013-02-21 17:26:09 -08001651 if x.parameters['ZUUL_CHANGE'] == '3':
1652 a_zref = x.parameters['ZUUL_REF']
1653 if x.parameters['ZUUL_CHANGE'] == '4':
1654 b_zref = x.parameters['ZUUL_REF']
1655 if x.parameters['ZUUL_CHANGE'] == '5':
1656 c_zref = x.parameters['ZUUL_REF']
1657 if x.parameters['ZUUL_CHANGE'] == '6':
1658 d_zref = x.parameters['ZUUL_REF']
1659
1660 # There are... four... refs.
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001661 self.assertIsNotNone(a_zref)
1662 self.assertIsNotNone(b_zref)
1663 self.assertIsNotNone(c_zref)
1664 self.assertIsNotNone(d_zref)
James E. Blair7d0dedc2013-02-21 17:26:09 -08001665
1666 # And they should all be different
1667 refs = set([a_zref, b_zref, c_zref, d_zref])
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001668 self.assertEqual(len(refs), 4)
James E. Blair7d0dedc2013-02-21 17:26:09 -08001669
1670 # a ref should have a, not b, and should not be in project2
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001671 self.assertTrue(self.ref_has_change(a_zref, A))
1672 self.assertFalse(self.ref_has_change(a_zref, B))
1673 self.assertFalse(self.ref_has_change(a_zref, M2))
James E. Blair7d0dedc2013-02-21 17:26:09 -08001674
1675 # b ref should have a and b, and should not be in project2
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001676 self.assertTrue(self.ref_has_change(b_zref, A))
1677 self.assertTrue(self.ref_has_change(b_zref, B))
1678 self.assertFalse(self.ref_has_change(b_zref, M2))
James E. Blair7d0dedc2013-02-21 17:26:09 -08001679
1680 # c ref should have a and b in 1, c in 2
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001681 self.assertTrue(self.ref_has_change(c_zref, A))
1682 self.assertTrue(self.ref_has_change(c_zref, B))
1683 self.assertTrue(self.ref_has_change(c_zref, C))
1684 self.assertFalse(self.ref_has_change(c_zref, D))
James E. Blair7d0dedc2013-02-21 17:26:09 -08001685
1686 # d ref should have a and b in 1, c and d in 2
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001687 self.assertTrue(self.ref_has_change(d_zref, A))
1688 self.assertTrue(self.ref_has_change(d_zref, B))
1689 self.assertTrue(self.ref_has_change(d_zref, C))
1690 self.assertTrue(self.ref_has_change(d_zref, D))
James E. Blair7d0dedc2013-02-21 17:26:09 -08001691
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001692 self.worker.hold_jobs_in_build = False
1693 self.worker.release()
James E. Blair7d0dedc2013-02-21 17:26:09 -08001694 self.waitUntilSettled()
1695
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001696 self.assertEqual(A.data['status'], 'MERGED')
1697 self.assertEqual(A.reported, 2)
1698 self.assertEqual(B.data['status'], 'MERGED')
1699 self.assertEqual(B.reported, 2)
1700 self.assertEqual(C.data['status'], 'MERGED')
1701 self.assertEqual(C.reported, 2)
1702 self.assertEqual(D.data['status'], 'MERGED')
1703 self.assertEqual(D.reported, 2)
James E. Blair70c71582013-03-06 08:50:50 -08001704
James E. Blair4a28a882013-08-23 15:17:33 -07001705 def test_rerun_on_error(self):
1706 "Test that if a worker fails to run a job, it is run again"
1707 self.worker.hold_jobs_in_build = True
1708 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1709 A.addApproval('CRVW', 2)
1710 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1711 self.waitUntilSettled()
1712
1713 self.builds[0].run_error = True
1714 self.worker.hold_jobs_in_build = False
1715 self.worker.release()
1716 self.waitUntilSettled()
1717 self.assertEqual(self.countJobResults(self.history, 'RUN_ERROR'), 1)
1718 self.assertEqual(self.countJobResults(self.history, 'SUCCESS'), 3)
1719
James E. Blair412e5582013-04-22 15:50:12 -07001720 def test_statsd(self):
1721 "Test each of the statsd methods used in the scheduler"
1722 import extras
1723 statsd = extras.try_import('statsd.statsd')
1724 statsd.incr('test-incr')
1725 statsd.timing('test-timing', 3)
Alex Gaynor813d39b2014-05-17 16:17:16 -07001726 statsd.gauge('test-gauge', 12)
James E. Blair412e5582013-04-22 15:50:12 -07001727 self.assertReportedStat('test-incr', '1|c')
1728 self.assertReportedStat('test-timing', '3|ms')
Alex Gaynor813d39b2014-05-17 16:17:16 -07001729 self.assertReportedStat('test-gauge', '12|g')
James E. Blair412e5582013-04-22 15:50:12 -07001730
James E. Blairdad52252014-02-07 16:59:17 -08001731 def test_stuck_job_cleanup(self):
1732 "Test that pending jobs are cleaned up if removed from layout"
James E. Blair18c64442014-03-18 10:14:45 -07001733 # This job won't be registered at startup because it is not in
1734 # the standard layout, but we need it to already be registerd
1735 # for when we reconfigure, as that is when Zuul will attempt
1736 # to run the new job.
1737 self.worker.registerFunction('build:gate-noop')
James E. Blairdad52252014-02-07 16:59:17 -08001738 self.gearman_server.hold_jobs_in_queue = True
1739 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1740 A.addApproval('CRVW', 2)
1741 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1742 self.waitUntilSettled()
1743 self.assertEqual(len(self.gearman_server.getQueue()), 1)
1744
1745 self.config.set('zuul', 'layout_config',
1746 'tests/fixtures/layout-no-jobs.yaml')
1747 self.sched.reconfigure(self.config)
1748 self.waitUntilSettled()
1749
James E. Blair18c64442014-03-18 10:14:45 -07001750 self.gearman_server.release('gate-noop')
James E. Blairdad52252014-02-07 16:59:17 -08001751 self.waitUntilSettled()
1752 self.assertEqual(len(self.gearman_server.getQueue()), 0)
1753 self.assertTrue(self.sched._areAllBuildsComplete())
1754
1755 self.assertEqual(len(self.history), 1)
James E. Blair18c64442014-03-18 10:14:45 -07001756 self.assertEqual(self.history[0].name, 'gate-noop')
James E. Blairdad52252014-02-07 16:59:17 -08001757 self.assertEqual(self.history[0].result, 'SUCCESS')
1758
James E. Blair70c71582013-03-06 08:50:50 -08001759 def test_file_jobs(self):
1760 "Test that file jobs run only when appropriate"
1761 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1762 A.addPatchset(['pip-requires'])
1763 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1764 A.addApproval('CRVW', 2)
1765 B.addApproval('CRVW', 2)
1766 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1767 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1768 self.waitUntilSettled()
1769
Monty Taylor6bef8ef2013-06-02 08:17:12 -04001770 testfile_jobs = [x for x in self.history
James E. Blair70c71582013-03-06 08:50:50 -08001771 if x.name == 'project-testfile']
1772
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001773 self.assertEqual(len(testfile_jobs), 1)
1774 self.assertEqual(testfile_jobs[0].changes, '1,2')
1775 self.assertEqual(A.data['status'], 'MERGED')
1776 self.assertEqual(A.reported, 2)
1777 self.assertEqual(B.data['status'], 'MERGED')
1778 self.assertEqual(B.reported, 2)
James E. Blair3c5e5b52013-04-26 11:17:03 -07001779
Maru Newby3fe5f852015-01-13 04:22:14 +00001780 def _test_skip_if_jobs(self, branch, should_skip):
1781 "Test that jobs with a skip-if filter run only when appropriate"
1782 self.config.set('zuul', 'layout_config',
1783 'tests/fixtures/layout-skip-if.yaml')
1784 self.sched.reconfigure(self.config)
1785 self.registerJobs()
1786
1787 change = self.fake_gerrit.addFakeChange('org/project',
1788 branch,
1789 'test skip-if')
1790 self.fake_gerrit.addEvent(change.getPatchsetCreatedEvent(1))
1791 self.waitUntilSettled()
1792
1793 tested_change_ids = [x.changes[0] for x in self.history
1794 if x.name == 'project-test-skip-if']
1795
1796 if should_skip:
1797 self.assertEqual([], tested_change_ids)
1798 else:
1799 self.assertIn(change.data['number'], tested_change_ids)
1800
1801 def test_skip_if_match_skips_job(self):
1802 self._test_skip_if_jobs(branch='master', should_skip=True)
1803
1804 def test_skip_if_no_match_runs_job(self):
1805 self._test_skip_if_jobs(branch='mp', should_skip=False)
1806
James E. Blair3c5e5b52013-04-26 11:17:03 -07001807 def test_test_config(self):
1808 "Test that we can test the config"
1809 sched = zuul.scheduler.Scheduler()
James E. Blair6c358e72013-07-29 17:06:47 -07001810 sched.registerTrigger(None, 'gerrit')
James E. Blair63bb0ef2013-07-29 17:14:51 -07001811 sched.registerTrigger(None, 'timer')
James E. Blairc494d542014-08-06 09:23:52 -07001812 sched.registerTrigger(None, 'zuul')
Clark Boylanb640e052014-04-03 16:41:46 -07001813 sched.testConfig(self.config.get('zuul', 'layout_config'))
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001814
1815 def test_build_description(self):
1816 "Test that build descriptions update"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001817 self.worker.registerFunction('set_description:' +
1818 self.worker.worker_id)
1819
1820 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1821 A.addApproval('CRVW', 2)
1822 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1823 self.waitUntilSettled()
Monty Taylor6bef8ef2013-06-02 08:17:12 -04001824 desc = self.history[0].description
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001825 self.log.debug("Description: %s" % desc)
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001826 self.assertTrue(re.search("Branch.*master", desc))
1827 self.assertTrue(re.search("Pipeline.*gate", desc))
1828 self.assertTrue(re.search("project-merge.*SUCCESS", desc))
1829 self.assertTrue(re.search("project-test1.*SUCCESS", desc))
1830 self.assertTrue(re.search("project-test2.*SUCCESS", desc))
1831 self.assertTrue(re.search("Reported result.*SUCCESS", desc))
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001832
James E. Blairc8a1e052014-02-25 09:29:26 -08001833 def test_queue_names(self):
1834 "Test shared change queue names"
1835 project1 = self.sched.layout.projects['org/project1']
1836 project2 = self.sched.layout.projects['org/project2']
1837 q1 = self.sched.layout.pipelines['gate'].getQueue(project1)
1838 q2 = self.sched.layout.pipelines['gate'].getQueue(project2)
1839 self.assertEqual(q1.name, 'integration')
1840 self.assertEqual(q2.name, 'integration')
1841
1842 self.config.set('zuul', 'layout_config',
1843 'tests/fixtures/layout-bad-queue.yaml')
1844 with testtools.ExpectedException(
1845 Exception, "More than one name assigned to change queue"):
1846 self.sched.reconfigure(self.config)
1847
James E. Blair64ed6f22013-07-10 14:07:23 -07001848 def test_queue_precedence(self):
1849 "Test that queue precedence works"
1850
1851 self.gearman_server.hold_jobs_in_queue = True
James E. Blair8de58bd2013-07-18 16:23:33 -07001852 self.worker.hold_jobs_in_build = True
James E. Blair64ed6f22013-07-10 14:07:23 -07001853 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1854 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1855 A.addApproval('CRVW', 2)
1856 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1857
1858 self.waitUntilSettled()
1859 self.gearman_server.hold_jobs_in_queue = False
1860 self.gearman_server.release()
1861 self.waitUntilSettled()
1862
James E. Blair8de58bd2013-07-18 16:23:33 -07001863 # Run one build at a time to ensure non-race order:
1864 for x in range(6):
1865 self.release(self.builds[0])
1866 self.waitUntilSettled()
1867 self.worker.hold_jobs_in_build = False
1868 self.waitUntilSettled()
1869
James E. Blair64ed6f22013-07-10 14:07:23 -07001870 self.log.debug(self.history)
1871 self.assertEqual(self.history[0].pipeline, 'gate')
1872 self.assertEqual(self.history[1].pipeline, 'check')
1873 self.assertEqual(self.history[2].pipeline, 'gate')
1874 self.assertEqual(self.history[3].pipeline, 'gate')
1875 self.assertEqual(self.history[4].pipeline, 'check')
1876 self.assertEqual(self.history[5].pipeline, 'check')
1877
Clark Boylana5edbe42014-06-03 16:39:10 -07001878 def test_json_status(self):
James E. Blair1843a552013-07-03 14:19:52 -07001879 "Test that we can retrieve JSON status info"
1880 self.worker.hold_jobs_in_build = True
1881 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1882 A.addApproval('CRVW', 2)
1883 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1884 self.waitUntilSettled()
1885
1886 port = self.webapp.server.socket.getsockname()[1]
1887
Yuriy Taradaya6d452f2014-04-16 12:36:20 +04001888 req = urllib2.Request("http://localhost:%s/status.json" % port)
Yuriy Taradaya6d452f2014-04-16 12:36:20 +04001889 f = urllib2.urlopen(req)
Clark Boylanaa4f2e72014-06-03 21:22:40 -07001890 headers = f.info()
1891 self.assertIn('Content-Length', headers)
1892 self.assertIn('Content-Type', headers)
1893 self.assertEqual(headers['Content-Type'],
1894 'application/json; charset=UTF-8')
1895 self.assertIn('Last-Modified', headers)
James E. Blair1843a552013-07-03 14:19:52 -07001896 data = f.read()
1897
1898 self.worker.hold_jobs_in_build = False
1899 self.worker.release()
1900 self.waitUntilSettled()
1901
1902 data = json.loads(data)
1903 status_jobs = set()
1904 for p in data['pipelines']:
1905 for q in p['change_queues']:
Clark Boylanaf2476f2014-01-23 14:47:36 -08001906 if q['dependent']:
1907 self.assertEqual(q['window'], 20)
1908 else:
1909 self.assertEqual(q['window'], 0)
James E. Blair1843a552013-07-03 14:19:52 -07001910 for head in q['heads']:
1911 for change in head:
Clark Boylanaf2476f2014-01-23 14:47:36 -08001912 self.assertTrue(change['active'])
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001913 self.assertEqual(change['id'], '1,1')
James E. Blair1843a552013-07-03 14:19:52 -07001914 for job in change['jobs']:
1915 status_jobs.add(job['name'])
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001916 self.assertIn('project-merge', status_jobs)
1917 self.assertIn('project-test1', status_jobs)
1918 self.assertIn('project-test2', status_jobs)
James E. Blair1843a552013-07-03 14:19:52 -07001919
James E. Blairc3d428e2013-12-03 15:06:48 -08001920 def test_merging_queues(self):
1921 "Test that transitively-connected change queues are merged"
1922 self.config.set('zuul', 'layout_config',
1923 'tests/fixtures/layout-merge-queues.yaml')
1924 self.sched.reconfigure(self.config)
1925 self.assertEqual(len(self.sched.layout.pipelines['gate'].queues), 1)
1926
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001927 def test_node_label(self):
1928 "Test that a job runs on a specific node label"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001929 self.worker.registerFunction('build:node-project-test1:debian')
1930
1931 A = self.fake_gerrit.addFakeChange('org/node-project', 'master', 'A')
1932 A.addApproval('CRVW', 2)
1933 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1934 self.waitUntilSettled()
James E. Blair4ca985f2013-05-30 12:27:43 -07001935
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001936 self.assertIsNone(self.getJobFromHistory('node-project-merge').node)
1937 self.assertEqual(self.getJobFromHistory('node-project-test1').node,
1938 'debian')
1939 self.assertIsNone(self.getJobFromHistory('node-project-test2').node)
James E. Blaircdccd972013-07-01 12:10:22 -07001940
1941 def test_live_reconfiguration(self):
1942 "Test that live reconfiguration works"
1943 self.worker.hold_jobs_in_build = True
1944 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1945 A.addApproval('CRVW', 2)
1946 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1947 self.waitUntilSettled()
1948
1949 self.sched.reconfigure(self.config)
1950
1951 self.worker.hold_jobs_in_build = False
1952 self.worker.release()
1953 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001954 self.assertEqual(self.getJobFromHistory('project-merge').result,
1955 'SUCCESS')
1956 self.assertEqual(self.getJobFromHistory('project-test1').result,
1957 'SUCCESS')
1958 self.assertEqual(self.getJobFromHistory('project-test2').result,
1959 'SUCCESS')
1960 self.assertEqual(A.data['status'], 'MERGED')
1961 self.assertEqual(A.reported, 2)
James E. Blair287c06d2013-07-24 10:39:30 -07001962
James E. Blaire712d9f2013-07-31 11:40:11 -07001963 def test_live_reconfiguration_functions(self):
1964 "Test live reconfiguration with a custom function"
1965 self.worker.registerFunction('build:node-project-test1:debian')
1966 self.worker.registerFunction('build:node-project-test1:wheezy')
1967 A = self.fake_gerrit.addFakeChange('org/node-project', 'master', 'A')
1968 A.addApproval('CRVW', 2)
1969 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1970 self.waitUntilSettled()
1971
1972 self.assertIsNone(self.getJobFromHistory('node-project-merge').node)
1973 self.assertEqual(self.getJobFromHistory('node-project-test1').node,
1974 'debian')
1975 self.assertIsNone(self.getJobFromHistory('node-project-test2').node)
1976
1977 self.config.set('zuul', 'layout_config',
1978 'tests/fixtures/layout-live-'
1979 'reconfiguration-functions.yaml')
1980 self.sched.reconfigure(self.config)
1981 self.worker.build_history = []
1982
1983 B = self.fake_gerrit.addFakeChange('org/node-project', 'master', 'B')
1984 B.addApproval('CRVW', 2)
1985 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1986 self.waitUntilSettled()
1987
1988 self.assertIsNone(self.getJobFromHistory('node-project-merge').node)
1989 self.assertEqual(self.getJobFromHistory('node-project-test1').node,
1990 'wheezy')
1991 self.assertIsNone(self.getJobFromHistory('node-project-test2').node)
1992
James E. Blair287c06d2013-07-24 10:39:30 -07001993 def test_delayed_repo_init(self):
1994 self.config.set('zuul', 'layout_config',
1995 'tests/fixtures/layout-delayed-repo-init.yaml')
1996 self.sched.reconfigure(self.config)
1997
1998 self.init_repo("org/new-project")
1999 A = self.fake_gerrit.addFakeChange('org/new-project', 'master', 'A')
2000
2001 A.addApproval('CRVW', 2)
2002 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2003 self.waitUntilSettled()
2004 self.assertEqual(self.getJobFromHistory('project-merge').result,
2005 'SUCCESS')
2006 self.assertEqual(self.getJobFromHistory('project-test1').result,
2007 'SUCCESS')
2008 self.assertEqual(self.getJobFromHistory('project-test2').result,
2009 'SUCCESS')
2010 self.assertEqual(A.data['status'], 'MERGED')
2011 self.assertEqual(A.reported, 2)
James E. Blair63bb0ef2013-07-29 17:14:51 -07002012
Clark Boylan6dbbc482013-10-18 10:57:31 -07002013 def test_repo_deleted(self):
2014 self.config.set('zuul', 'layout_config',
2015 'tests/fixtures/layout-repo-deleted.yaml')
2016 self.sched.reconfigure(self.config)
2017
2018 self.init_repo("org/delete-project")
2019 A = self.fake_gerrit.addFakeChange('org/delete-project', 'master', 'A')
2020
2021 A.addApproval('CRVW', 2)
2022 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2023 self.waitUntilSettled()
2024 self.assertEqual(self.getJobFromHistory('project-merge').result,
2025 'SUCCESS')
2026 self.assertEqual(self.getJobFromHistory('project-test1').result,
2027 'SUCCESS')
2028 self.assertEqual(self.getJobFromHistory('project-test2').result,
2029 'SUCCESS')
2030 self.assertEqual(A.data['status'], 'MERGED')
2031 self.assertEqual(A.reported, 2)
2032
2033 # Delete org/new-project zuul repo. Should be recloned.
2034 shutil.rmtree(os.path.join(self.git_root, "org/delete-project"))
2035
2036 B = self.fake_gerrit.addFakeChange('org/delete-project', 'master', 'B')
2037
2038 B.addApproval('CRVW', 2)
2039 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2040 self.waitUntilSettled()
2041 self.assertEqual(self.getJobFromHistory('project-merge').result,
2042 'SUCCESS')
2043 self.assertEqual(self.getJobFromHistory('project-test1').result,
2044 'SUCCESS')
2045 self.assertEqual(self.getJobFromHistory('project-test2').result,
2046 'SUCCESS')
2047 self.assertEqual(B.data['status'], 'MERGED')
2048 self.assertEqual(B.reported, 2)
2049
James E. Blair63bb0ef2013-07-29 17:14:51 -07002050 def test_timer(self):
2051 "Test that a periodic job is triggered"
2052 self.worker.hold_jobs_in_build = True
2053 self.config.set('zuul', 'layout_config',
2054 'tests/fixtures/layout-timer.yaml')
2055 self.sched.reconfigure(self.config)
2056 self.registerJobs()
2057
Clark Boylan3ee090a2014-04-03 20:55:09 -07002058 # The pipeline triggers every second, so we should have seen
2059 # several by now.
2060 time.sleep(5)
James E. Blair63bb0ef2013-07-29 17:14:51 -07002061 self.waitUntilSettled()
Clark Boylan3ee090a2014-04-03 20:55:09 -07002062
2063 self.assertEqual(len(self.builds), 2)
2064
James E. Blair63bb0ef2013-07-29 17:14:51 -07002065 port = self.webapp.server.socket.getsockname()[1]
2066
2067 f = urllib.urlopen("http://localhost:%s/status.json" % port)
2068 data = f.read()
2069
2070 self.worker.hold_jobs_in_build = False
Clark Boylan3ee090a2014-04-03 20:55:09 -07002071 # Stop queuing timer triggered jobs so that the assertions
2072 # below don't race against more jobs being queued.
2073 self.config.set('zuul', 'layout_config',
2074 'tests/fixtures/layout-no-timer.yaml')
2075 self.sched.reconfigure(self.config)
2076 self.registerJobs()
James E. Blair63bb0ef2013-07-29 17:14:51 -07002077 self.worker.release()
2078 self.waitUntilSettled()
2079
2080 self.assertEqual(self.getJobFromHistory(
2081 'project-bitrot-stable-old').result, 'SUCCESS')
2082 self.assertEqual(self.getJobFromHistory(
2083 'project-bitrot-stable-older').result, 'SUCCESS')
2084
2085 data = json.loads(data)
2086 status_jobs = set()
2087 for p in data['pipelines']:
2088 for q in p['change_queues']:
2089 for head in q['heads']:
2090 for change in head:
Alex Gaynorddb9ef32013-09-16 21:04:58 -07002091 self.assertEqual(change['id'], None)
James E. Blair63bb0ef2013-07-29 17:14:51 -07002092 for job in change['jobs']:
2093 status_jobs.add(job['name'])
2094 self.assertIn('project-bitrot-stable-old', status_jobs)
2095 self.assertIn('project-bitrot-stable-older', status_jobs)
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002096
James E. Blair4f6033c2014-03-27 15:49:09 -07002097 def test_idle(self):
2098 "Test that frequent periodic jobs work"
2099 self.worker.hold_jobs_in_build = True
James E. Blair4f6033c2014-03-27 15:49:09 -07002100
Clark Boylan3ee090a2014-04-03 20:55:09 -07002101 for x in range(1, 3):
2102 # Test that timer triggers periodic jobs even across
2103 # layout config reloads.
2104 # Start timer trigger
2105 self.config.set('zuul', 'layout_config',
2106 'tests/fixtures/layout-idle.yaml')
2107 self.sched.reconfigure(self.config)
2108 self.registerJobs()
James E. Blair4f6033c2014-03-27 15:49:09 -07002109
Clark Boylan3ee090a2014-04-03 20:55:09 -07002110 # The pipeline triggers every second, so we should have seen
2111 # several by now.
2112 time.sleep(5)
2113 self.waitUntilSettled()
2114
2115 # Stop queuing timer triggered jobs so that the assertions
2116 # below don't race against more jobs being queued.
2117 self.config.set('zuul', 'layout_config',
2118 'tests/fixtures/layout-no-timer.yaml')
2119 self.sched.reconfigure(self.config)
2120 self.registerJobs()
2121
2122 self.assertEqual(len(self.builds), 2)
2123 self.worker.release('.*')
2124 self.waitUntilSettled()
2125 self.assertEqual(len(self.builds), 0)
2126 self.assertEqual(len(self.history), x * 2)
James E. Blair4f6033c2014-03-27 15:49:09 -07002127
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002128 def test_check_smtp_pool(self):
2129 self.config.set('zuul', 'layout_config',
2130 'tests/fixtures/layout-smtp.yaml')
2131 self.sched.reconfigure(self.config)
2132
2133 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2134 self.waitUntilSettled()
2135
2136 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2137 self.waitUntilSettled()
2138
James E. Blairff80a2f2013-12-27 13:24:06 -08002139 self.assertEqual(len(self.smtp_messages), 2)
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002140
2141 # A.messages only holds what FakeGerrit places in it. Thus we
2142 # work on the knowledge of what the first message should be as
2143 # it is only configured to go to SMTP.
2144
2145 self.assertEqual('zuul@example.com',
James E. Blairff80a2f2013-12-27 13:24:06 -08002146 self.smtp_messages[0]['from_email'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002147 self.assertEqual(['you@example.com'],
James E. Blairff80a2f2013-12-27 13:24:06 -08002148 self.smtp_messages[0]['to_email'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002149 self.assertEqual('Starting check jobs.',
James E. Blairff80a2f2013-12-27 13:24:06 -08002150 self.smtp_messages[0]['body'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002151
2152 self.assertEqual('zuul_from@example.com',
James E. Blairff80a2f2013-12-27 13:24:06 -08002153 self.smtp_messages[1]['from_email'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002154 self.assertEqual(['alternative_me@example.com'],
James E. Blairff80a2f2013-12-27 13:24:06 -08002155 self.smtp_messages[1]['to_email'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002156 self.assertEqual(A.messages[0],
James E. Blairff80a2f2013-12-27 13:24:06 -08002157 self.smtp_messages[1]['body'])
James E. Blairad28e912013-11-27 10:43:22 -08002158
James E. Blaire5910202013-12-27 09:50:31 -08002159 def test_timer_smtp(self):
2160 "Test that a periodic job is triggered"
Clark Boylan3ee090a2014-04-03 20:55:09 -07002161 self.worker.hold_jobs_in_build = True
James E. Blaire5910202013-12-27 09:50:31 -08002162 self.config.set('zuul', 'layout_config',
2163 'tests/fixtures/layout-timer-smtp.yaml')
2164 self.sched.reconfigure(self.config)
2165 self.registerJobs()
2166
Clark Boylan3ee090a2014-04-03 20:55:09 -07002167 # The pipeline triggers every second, so we should have seen
2168 # several by now.
2169 time.sleep(5)
James E. Blaire5910202013-12-27 09:50:31 -08002170 self.waitUntilSettled()
2171
Clark Boylan3ee090a2014-04-03 20:55:09 -07002172 self.assertEqual(len(self.builds), 2)
2173 self.worker.release('.*')
2174 self.waitUntilSettled()
2175 self.assertEqual(len(self.history), 2)
2176
James E. Blaire5910202013-12-27 09:50:31 -08002177 self.assertEqual(self.getJobFromHistory(
2178 'project-bitrot-stable-old').result, 'SUCCESS')
2179 self.assertEqual(self.getJobFromHistory(
2180 'project-bitrot-stable-older').result, 'SUCCESS')
2181
James E. Blairff80a2f2013-12-27 13:24:06 -08002182 self.assertEqual(len(self.smtp_messages), 1)
James E. Blaire5910202013-12-27 09:50:31 -08002183
2184 # A.messages only holds what FakeGerrit places in it. Thus we
2185 # work on the knowledge of what the first message should be as
2186 # it is only configured to go to SMTP.
2187
2188 self.assertEqual('zuul_from@example.com',
James E. Blairff80a2f2013-12-27 13:24:06 -08002189 self.smtp_messages[0]['from_email'])
James E. Blaire5910202013-12-27 09:50:31 -08002190 self.assertEqual(['alternative_me@example.com'],
James E. Blairff80a2f2013-12-27 13:24:06 -08002191 self.smtp_messages[0]['to_email'])
James E. Blaire5910202013-12-27 09:50:31 -08002192 self.assertIn('Subject: Periodic check for org/project succeeded',
James E. Blairff80a2f2013-12-27 13:24:06 -08002193 self.smtp_messages[0]['headers'])
James E. Blaire5910202013-12-27 09:50:31 -08002194
Clark Boylan3ee090a2014-04-03 20:55:09 -07002195 # Stop queuing timer triggered jobs and let any that may have
2196 # queued through so that end of test assertions pass.
2197 self.config.set('zuul', 'layout_config',
2198 'tests/fixtures/layout-no-timer.yaml')
2199 self.sched.reconfigure(self.config)
2200 self.registerJobs()
James E. Blairf8058972014-08-15 16:09:16 -07002201 self.waitUntilSettled()
Clark Boylan3ee090a2014-04-03 20:55:09 -07002202 self.worker.release('.*')
2203 self.waitUntilSettled()
2204
James E. Blairad28e912013-11-27 10:43:22 -08002205 def test_client_enqueue(self):
2206 "Test that the RPC client can enqueue a change"
2207 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2208 A.addApproval('CRVW', 2)
2209 A.addApproval('APRV', 1)
2210
2211 client = zuul.rpcclient.RPCClient('127.0.0.1',
2212 self.gearman_server.port)
2213 r = client.enqueue(pipeline='gate',
2214 project='org/project',
2215 trigger='gerrit',
James E. Blair36658cf2013-12-06 17:53:48 -08002216 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08002217 self.waitUntilSettled()
2218 self.assertEqual(self.getJobFromHistory('project-merge').result,
2219 'SUCCESS')
2220 self.assertEqual(self.getJobFromHistory('project-test1').result,
2221 'SUCCESS')
2222 self.assertEqual(self.getJobFromHistory('project-test2').result,
2223 'SUCCESS')
2224 self.assertEqual(A.data['status'], 'MERGED')
2225 self.assertEqual(A.reported, 2)
2226 self.assertEqual(r, True)
2227
2228 def test_client_enqueue_negative(self):
2229 "Test that the RPC client returns errors"
2230 client = zuul.rpcclient.RPCClient('127.0.0.1',
2231 self.gearman_server.port)
2232 with testtools.ExpectedException(zuul.rpcclient.RPCFailure,
2233 "Invalid project"):
2234 r = client.enqueue(pipeline='gate',
2235 project='project-does-not-exist',
2236 trigger='gerrit',
James E. Blair36658cf2013-12-06 17:53:48 -08002237 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08002238 client.shutdown()
2239 self.assertEqual(r, False)
2240
2241 with testtools.ExpectedException(zuul.rpcclient.RPCFailure,
2242 "Invalid pipeline"):
2243 r = client.enqueue(pipeline='pipeline-does-not-exist',
2244 project='org/project',
2245 trigger='gerrit',
James E. Blair36658cf2013-12-06 17:53:48 -08002246 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08002247 client.shutdown()
2248 self.assertEqual(r, False)
2249
2250 with testtools.ExpectedException(zuul.rpcclient.RPCFailure,
2251 "Invalid trigger"):
2252 r = client.enqueue(pipeline='gate',
2253 project='org/project',
2254 trigger='trigger-does-not-exist',
James E. Blair36658cf2013-12-06 17:53:48 -08002255 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08002256 client.shutdown()
2257 self.assertEqual(r, False)
2258
2259 with testtools.ExpectedException(zuul.rpcclient.RPCFailure,
2260 "Invalid change"):
2261 r = client.enqueue(pipeline='gate',
2262 project='org/project',
2263 trigger='gerrit',
James E. Blair36658cf2013-12-06 17:53:48 -08002264 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08002265 client.shutdown()
2266 self.assertEqual(r, False)
2267
2268 self.waitUntilSettled()
2269 self.assertEqual(len(self.history), 0)
2270 self.assertEqual(len(self.builds), 0)
James E. Blair36658cf2013-12-06 17:53:48 -08002271
2272 def test_client_promote(self):
2273 "Test that the RPC client can promote a change"
2274 self.worker.hold_jobs_in_build = True
2275 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2276 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2277 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
2278 A.addApproval('CRVW', 2)
2279 B.addApproval('CRVW', 2)
2280 C.addApproval('CRVW', 2)
2281
2282 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2283 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2284 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
2285
2286 self.waitUntilSettled()
2287
Sean Daguef39b9ca2014-01-10 21:34:35 -05002288 items = self.sched.layout.pipelines['gate'].getAllItems()
2289 enqueue_times = {}
2290 for item in items:
2291 enqueue_times[str(item.change)] = item.enqueue_time
2292
James E. Blair36658cf2013-12-06 17:53:48 -08002293 client = zuul.rpcclient.RPCClient('127.0.0.1',
2294 self.gearman_server.port)
2295 r = client.promote(pipeline='gate',
2296 change_ids=['2,1', '3,1'])
2297
Sean Daguef39b9ca2014-01-10 21:34:35 -05002298 # ensure that enqueue times are durable
2299 items = self.sched.layout.pipelines['gate'].getAllItems()
2300 for item in items:
2301 self.assertEqual(
2302 enqueue_times[str(item.change)], item.enqueue_time)
2303
James E. Blair78acec92014-02-06 07:11:32 -08002304 self.waitUntilSettled()
James E. Blair36658cf2013-12-06 17:53:48 -08002305 self.worker.release('.*-merge')
2306 self.waitUntilSettled()
2307 self.worker.release('.*-merge')
2308 self.waitUntilSettled()
2309 self.worker.release('.*-merge')
2310 self.waitUntilSettled()
2311
2312 self.assertEqual(len(self.builds), 6)
2313 self.assertEqual(self.builds[0].name, 'project-test1')
2314 self.assertEqual(self.builds[1].name, 'project-test2')
2315 self.assertEqual(self.builds[2].name, 'project-test1')
2316 self.assertEqual(self.builds[3].name, 'project-test2')
2317 self.assertEqual(self.builds[4].name, 'project-test1')
2318 self.assertEqual(self.builds[5].name, 'project-test2')
2319
2320 self.assertTrue(self.job_has_changes(self.builds[0], B))
2321 self.assertFalse(self.job_has_changes(self.builds[0], A))
2322 self.assertFalse(self.job_has_changes(self.builds[0], C))
2323
2324 self.assertTrue(self.job_has_changes(self.builds[2], B))
2325 self.assertTrue(self.job_has_changes(self.builds[2], C))
2326 self.assertFalse(self.job_has_changes(self.builds[2], A))
2327
2328 self.assertTrue(self.job_has_changes(self.builds[4], B))
2329 self.assertTrue(self.job_has_changes(self.builds[4], C))
2330 self.assertTrue(self.job_has_changes(self.builds[4], A))
2331
2332 self.worker.release()
2333 self.waitUntilSettled()
2334
2335 self.assertEqual(A.data['status'], 'MERGED')
2336 self.assertEqual(A.reported, 2)
2337 self.assertEqual(B.data['status'], 'MERGED')
2338 self.assertEqual(B.reported, 2)
2339 self.assertEqual(C.data['status'], 'MERGED')
2340 self.assertEqual(C.reported, 2)
2341
2342 client.shutdown()
2343 self.assertEqual(r, True)
2344
2345 def test_client_promote_dependent(self):
2346 "Test that the RPC client can promote a dependent change"
2347 # C (depends on B) -> B -> A ; then promote C to get:
2348 # A -> C (depends on B) -> B
2349 self.worker.hold_jobs_in_build = True
2350 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2351 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2352 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
2353
2354 C.setDependsOn(B, 1)
2355
2356 A.addApproval('CRVW', 2)
2357 B.addApproval('CRVW', 2)
2358 C.addApproval('CRVW', 2)
2359
2360 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2361 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2362 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
2363
2364 self.waitUntilSettled()
2365
2366 client = zuul.rpcclient.RPCClient('127.0.0.1',
2367 self.gearman_server.port)
2368 r = client.promote(pipeline='gate',
2369 change_ids=['3,1'])
2370
James E. Blair78acec92014-02-06 07:11:32 -08002371 self.waitUntilSettled()
James E. Blair36658cf2013-12-06 17:53:48 -08002372 self.worker.release('.*-merge')
2373 self.waitUntilSettled()
2374 self.worker.release('.*-merge')
2375 self.waitUntilSettled()
2376 self.worker.release('.*-merge')
2377 self.waitUntilSettled()
2378
2379 self.assertEqual(len(self.builds), 6)
2380 self.assertEqual(self.builds[0].name, 'project-test1')
2381 self.assertEqual(self.builds[1].name, 'project-test2')
2382 self.assertEqual(self.builds[2].name, 'project-test1')
2383 self.assertEqual(self.builds[3].name, 'project-test2')
2384 self.assertEqual(self.builds[4].name, 'project-test1')
2385 self.assertEqual(self.builds[5].name, 'project-test2')
2386
2387 self.assertTrue(self.job_has_changes(self.builds[0], B))
2388 self.assertFalse(self.job_has_changes(self.builds[0], A))
2389 self.assertFalse(self.job_has_changes(self.builds[0], C))
2390
2391 self.assertTrue(self.job_has_changes(self.builds[2], B))
2392 self.assertTrue(self.job_has_changes(self.builds[2], C))
2393 self.assertFalse(self.job_has_changes(self.builds[2], A))
2394
2395 self.assertTrue(self.job_has_changes(self.builds[4], B))
2396 self.assertTrue(self.job_has_changes(self.builds[4], C))
2397 self.assertTrue(self.job_has_changes(self.builds[4], A))
2398
2399 self.worker.release()
2400 self.waitUntilSettled()
2401
2402 self.assertEqual(A.data['status'], 'MERGED')
2403 self.assertEqual(A.reported, 2)
2404 self.assertEqual(B.data['status'], 'MERGED')
2405 self.assertEqual(B.reported, 2)
2406 self.assertEqual(C.data['status'], 'MERGED')
2407 self.assertEqual(C.reported, 2)
2408
2409 client.shutdown()
2410 self.assertEqual(r, True)
2411
2412 def test_client_promote_negative(self):
2413 "Test that the RPC client returns errors for promotion"
2414 self.worker.hold_jobs_in_build = True
2415 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2416 A.addApproval('CRVW', 2)
2417 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2418 self.waitUntilSettled()
2419
2420 client = zuul.rpcclient.RPCClient('127.0.0.1',
2421 self.gearman_server.port)
2422
2423 with testtools.ExpectedException(zuul.rpcclient.RPCFailure):
2424 r = client.promote(pipeline='nonexistent',
2425 change_ids=['2,1', '3,1'])
2426 client.shutdown()
2427 self.assertEqual(r, False)
2428
2429 with testtools.ExpectedException(zuul.rpcclient.RPCFailure):
2430 r = client.promote(pipeline='gate',
2431 change_ids=['4,1'])
2432 client.shutdown()
2433 self.assertEqual(r, False)
2434
2435 self.worker.hold_jobs_in_build = False
2436 self.worker.release()
2437 self.waitUntilSettled()
Clark Boylan7603a372014-01-21 11:43:20 -08002438
2439 def test_queue_rate_limiting(self):
2440 "Test that DependentPipelines are rate limited with dep across window"
2441 self.config.set('zuul', 'layout_config',
2442 'tests/fixtures/layout-rate-limit.yaml')
2443 self.sched.reconfigure(self.config)
2444 self.worker.hold_jobs_in_build = True
2445 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2446 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2447 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
2448
2449 C.setDependsOn(B, 1)
2450 self.worker.addFailTest('project-test1', A)
2451
2452 A.addApproval('CRVW', 2)
2453 B.addApproval('CRVW', 2)
2454 C.addApproval('CRVW', 2)
2455
2456 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2457 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2458 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
2459 self.waitUntilSettled()
2460
2461 # Only A and B will have their merge jobs queued because
2462 # window is 2.
2463 self.assertEqual(len(self.builds), 2)
2464 self.assertEqual(self.builds[0].name, 'project-merge')
2465 self.assertEqual(self.builds[1].name, 'project-merge')
2466
2467 self.worker.release('.*-merge')
2468 self.waitUntilSettled()
2469 self.worker.release('.*-merge')
2470 self.waitUntilSettled()
2471
2472 # Only A and B will have their test jobs queued because
2473 # window is 2.
2474 self.assertEqual(len(self.builds), 4)
2475 self.assertEqual(self.builds[0].name, 'project-test1')
2476 self.assertEqual(self.builds[1].name, 'project-test2')
2477 self.assertEqual(self.builds[2].name, 'project-test1')
2478 self.assertEqual(self.builds[3].name, 'project-test2')
2479
2480 self.worker.release('project-.*')
2481 self.waitUntilSettled()
2482
2483 queue = self.sched.layout.pipelines['gate'].queues[0]
2484 # A failed so window is reduced by 1 to 1.
2485 self.assertEqual(queue.window, 1)
2486 self.assertEqual(queue.window_floor, 1)
2487 self.assertEqual(A.data['status'], 'NEW')
2488
2489 # Gate is reset and only B's merge job is queued because
2490 # window shrunk to 1.
2491 self.assertEqual(len(self.builds), 1)
2492 self.assertEqual(self.builds[0].name, 'project-merge')
2493
2494 self.worker.release('.*-merge')
2495 self.waitUntilSettled()
2496
2497 # Only B's test jobs are queued because window is still 1.
2498 self.assertEqual(len(self.builds), 2)
2499 self.assertEqual(self.builds[0].name, 'project-test1')
2500 self.assertEqual(self.builds[1].name, 'project-test2')
2501
2502 self.worker.release('project-.*')
2503 self.waitUntilSettled()
2504
2505 # B was successfully merged so window is increased to 2.
2506 self.assertEqual(queue.window, 2)
2507 self.assertEqual(queue.window_floor, 1)
2508 self.assertEqual(B.data['status'], 'MERGED')
2509
2510 # Only C is left and its merge job is queued.
2511 self.assertEqual(len(self.builds), 1)
2512 self.assertEqual(self.builds[0].name, 'project-merge')
2513
2514 self.worker.release('.*-merge')
2515 self.waitUntilSettled()
2516
2517 # After successful merge job the test jobs for C are queued.
2518 self.assertEqual(len(self.builds), 2)
2519 self.assertEqual(self.builds[0].name, 'project-test1')
2520 self.assertEqual(self.builds[1].name, 'project-test2')
2521
2522 self.worker.release('project-.*')
2523 self.waitUntilSettled()
2524
2525 # C successfully merged so window is bumped to 3.
2526 self.assertEqual(queue.window, 3)
2527 self.assertEqual(queue.window_floor, 1)
2528 self.assertEqual(C.data['status'], 'MERGED')
2529
2530 def test_queue_rate_limiting_dependent(self):
2531 "Test that DependentPipelines are rate limited with dep in window"
2532 self.config.set('zuul', 'layout_config',
2533 'tests/fixtures/layout-rate-limit.yaml')
2534 self.sched.reconfigure(self.config)
2535 self.worker.hold_jobs_in_build = True
2536 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2537 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2538 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
2539
2540 B.setDependsOn(A, 1)
2541
2542 self.worker.addFailTest('project-test1', A)
2543
2544 A.addApproval('CRVW', 2)
2545 B.addApproval('CRVW', 2)
2546 C.addApproval('CRVW', 2)
2547
2548 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2549 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2550 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
2551 self.waitUntilSettled()
2552
2553 # Only A and B will have their merge jobs queued because
2554 # window is 2.
2555 self.assertEqual(len(self.builds), 2)
2556 self.assertEqual(self.builds[0].name, 'project-merge')
2557 self.assertEqual(self.builds[1].name, 'project-merge')
2558
2559 self.worker.release('.*-merge')
2560 self.waitUntilSettled()
2561 self.worker.release('.*-merge')
2562 self.waitUntilSettled()
2563
2564 # Only A and B will have their test jobs queued because
2565 # window is 2.
2566 self.assertEqual(len(self.builds), 4)
2567 self.assertEqual(self.builds[0].name, 'project-test1')
2568 self.assertEqual(self.builds[1].name, 'project-test2')
2569 self.assertEqual(self.builds[2].name, 'project-test1')
2570 self.assertEqual(self.builds[3].name, 'project-test2')
2571
2572 self.worker.release('project-.*')
2573 self.waitUntilSettled()
2574
2575 queue = self.sched.layout.pipelines['gate'].queues[0]
2576 # A failed so window is reduced by 1 to 1.
2577 self.assertEqual(queue.window, 1)
2578 self.assertEqual(queue.window_floor, 1)
2579 self.assertEqual(A.data['status'], 'NEW')
2580 self.assertEqual(B.data['status'], 'NEW')
2581
2582 # Gate is reset and only C's merge job is queued because
2583 # window shrunk to 1 and A and B were dequeued.
2584 self.assertEqual(len(self.builds), 1)
2585 self.assertEqual(self.builds[0].name, 'project-merge')
2586
2587 self.worker.release('.*-merge')
2588 self.waitUntilSettled()
2589
2590 # Only C's test jobs are queued because window is still 1.
2591 self.assertEqual(len(self.builds), 2)
2592 self.assertEqual(self.builds[0].name, 'project-test1')
2593 self.assertEqual(self.builds[1].name, 'project-test2')
2594
2595 self.worker.release('project-.*')
2596 self.waitUntilSettled()
2597
2598 # C was successfully merged so window is increased to 2.
2599 self.assertEqual(queue.window, 2)
2600 self.assertEqual(queue.window_floor, 1)
2601 self.assertEqual(C.data['status'], 'MERGED')
Joshua Heskethba8776a2014-01-12 14:35:40 +08002602
2603 def test_worker_update_metadata(self):
2604 "Test if a worker can send back metadata about itself"
2605 self.worker.hold_jobs_in_build = True
2606
2607 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2608 A.addApproval('CRVW', 2)
2609 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2610 self.waitUntilSettled()
2611
2612 self.assertEqual(len(self.launcher.builds), 1)
2613
2614 self.log.debug('Current builds:')
2615 self.log.debug(self.launcher.builds)
2616
2617 start = time.time()
2618 while True:
2619 if time.time() - start > 10:
2620 raise Exception("Timeout waiting for gearman server to report "
2621 + "back to the client")
2622 build = self.launcher.builds.values()[0]
2623 if build.worker.name == "My Worker":
2624 break
2625 else:
2626 time.sleep(0)
2627
2628 self.log.debug(build)
2629 self.assertEqual("My Worker", build.worker.name)
2630 self.assertEqual("localhost", build.worker.hostname)
2631 self.assertEqual(['127.0.0.1', '192.168.1.1'], build.worker.ips)
2632 self.assertEqual("zuul.example.org", build.worker.fqdn)
2633 self.assertEqual("FakeBuilder", build.worker.program)
2634 self.assertEqual("v1.1", build.worker.version)
2635 self.assertEqual({'something': 'else'}, build.worker.extra)
2636
2637 self.worker.hold_jobs_in_build = False
2638 self.worker.release()
2639 self.waitUntilSettled()
Joshua Hesketh3979e3e2014-03-04 11:21:10 +11002640
2641 def test_footer_message(self):
2642 "Test a pipeline's footer message is correctly added to the report."
2643 self.config.set('zuul', 'layout_config',
2644 'tests/fixtures/layout-footer-message.yaml')
2645 self.sched.reconfigure(self.config)
2646 self.registerJobs()
2647
2648 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2649 A.addApproval('CRVW', 2)
2650 self.worker.addFailTest('test1', A)
2651 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2652 self.waitUntilSettled()
2653
2654 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2655 B.addApproval('CRVW', 2)
2656 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2657 self.waitUntilSettled()
2658
2659 self.assertEqual(2, len(self.smtp_messages))
2660
2661 failure_body = """\
2662Build failed. For information on how to proceed, see \
2663http://wiki.example.org/Test_Failures
2664
2665- test1 http://logs.example.com/1/1/gate/test1/0 : FAILURE in 0s
2666- test2 http://logs.example.com/1/1/gate/test2/1 : SUCCESS in 0s
2667
2668For CI problems and help debugging, contact ci@example.org"""
2669
2670 success_body = """\
2671Build succeeded.
2672
2673- test1 http://logs.example.com/2/1/gate/test1/2 : SUCCESS in 0s
2674- test2 http://logs.example.com/2/1/gate/test2/3 : SUCCESS in 0s
2675
2676For CI problems and help debugging, contact ci@example.org"""
2677
2678 self.assertEqual(failure_body, self.smtp_messages[0]['body'])
2679 self.assertEqual(success_body, self.smtp_messages[1]['body'])
Joshua Heskethb7179772014-01-30 23:30:46 +11002680
2681 def test_merge_failure_reporters(self):
2682 """Check that the config is set up correctly"""
2683
2684 self.config.set('zuul', 'layout_config',
2685 'tests/fixtures/layout-merge-failure.yaml')
2686 self.sched.reconfigure(self.config)
2687 self.registerJobs()
2688
2689 self.assertEqual(
2690 "Merge Failed.\n\nThis change was unable to be automatically "
2691 "merged with the current state of the repository. Please rebase "
2692 "your change and upload a new patchset.",
2693 self.sched.layout.pipelines['check'].merge_failure_message)
2694 self.assertEqual(
2695 "The merge failed! For more information...",
2696 self.sched.layout.pipelines['gate'].merge_failure_message)
2697
2698 self.assertEqual(
2699 len(self.sched.layout.pipelines['check'].merge_failure_actions), 1)
2700 self.assertEqual(
2701 len(self.sched.layout.pipelines['gate'].merge_failure_actions), 2)
2702
2703 self.assertTrue(isinstance(
2704 self.sched.layout.pipelines['check'].merge_failure_actions[0].
2705 reporter, zuul.reporter.gerrit.Reporter))
2706
2707 self.assertTrue(
2708 (
2709 isinstance(self.sched.layout.pipelines['gate'].
2710 merge_failure_actions[0].reporter,
2711 zuul.reporter.smtp.Reporter) and
2712 isinstance(self.sched.layout.pipelines['gate'].
2713 merge_failure_actions[1].reporter,
2714 zuul.reporter.gerrit.Reporter)
2715 ) or (
2716 isinstance(self.sched.layout.pipelines['gate'].
2717 merge_failure_actions[0].reporter,
2718 zuul.reporter.gerrit.Reporter) and
2719 isinstance(self.sched.layout.pipelines['gate'].
2720 merge_failure_actions[1].reporter,
2721 zuul.reporter.smtp.Reporter)
2722 )
2723 )
2724
2725 def test_merge_failure_reports(self):
2726 """Check that when a change fails to merge the correct message is sent
2727 to the correct reporter"""
2728 self.config.set('zuul', 'layout_config',
2729 'tests/fixtures/layout-merge-failure.yaml')
2730 self.sched.reconfigure(self.config)
2731 self.registerJobs()
2732
2733 # Check a test failure isn't reported to SMTP
2734 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2735 A.addApproval('CRVW', 2)
2736 self.worker.addFailTest('project-test1', A)
2737 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2738 self.waitUntilSettled()
2739
2740 self.assertEqual(3, len(self.history)) # 3 jobs
2741 self.assertEqual(0, len(self.smtp_messages))
2742
2743 # Check a merge failure is reported to SMTP
2744 # B should be merged, but C will conflict with B
2745 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2746 B.addPatchset(['conflict'])
2747 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
2748 C.addPatchset(['conflict'])
2749 B.addApproval('CRVW', 2)
2750 C.addApproval('CRVW', 2)
2751 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2752 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
2753 self.waitUntilSettled()
2754
2755 self.assertEqual(6, len(self.history)) # A and B jobs
2756 self.assertEqual(1, len(self.smtp_messages))
2757 self.assertEqual('The merge failed! For more information...',
2758 self.smtp_messages[0]['body'])
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11002759
2760 def test_swift_instructions(self):
2761 "Test that the correct swift instructions are sent to the workers"
2762 self.config.set('zuul', 'layout_config',
2763 'tests/fixtures/layout-swift.yaml')
2764 self.sched.reconfigure(self.config)
2765 self.registerJobs()
2766
2767 self.worker.hold_jobs_in_build = True
2768 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2769
2770 A.addApproval('CRVW', 2)
2771 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2772 self.waitUntilSettled()
2773
2774 self.assertEqual(
2775 "https://storage.example.org/V1/AUTH_account/merge_logs/1/1/1/"
2776 "gate/test-merge/",
Joshua Hesketh76dee532014-07-03 15:39:13 +10002777 self.builds[0].parameters['SWIFT_logs_URL'][:-7])
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11002778 self.assertEqual(5,
2779 len(self.builds[0].parameters['SWIFT_logs_HMAC_BODY'].
2780 split('\n')))
2781 self.assertIn('SWIFT_logs_SIGNATURE', self.builds[0].parameters)
2782
2783 self.assertEqual(
2784 "https://storage.example.org/V1/AUTH_account/logs/1/1/1/"
2785 "gate/test-test/",
Joshua Hesketh76dee532014-07-03 15:39:13 +10002786 self.builds[1].parameters['SWIFT_logs_URL'][:-7])
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11002787 self.assertEqual(5,
2788 len(self.builds[1].parameters['SWIFT_logs_HMAC_BODY'].
2789 split('\n')))
2790 self.assertIn('SWIFT_logs_SIGNATURE', self.builds[1].parameters)
2791
2792 self.assertEqual(
2793 "https://storage.example.org/V1/AUTH_account/stash/1/1/1/"
2794 "gate/test-test/",
Joshua Hesketh76dee532014-07-03 15:39:13 +10002795 self.builds[1].parameters['SWIFT_MOSTLY_URL'][:-7])
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11002796 self.assertEqual(5,
2797 len(self.builds[1].
2798 parameters['SWIFT_MOSTLY_HMAC_BODY'].split('\n')))
2799 self.assertIn('SWIFT_MOSTLY_SIGNATURE', self.builds[1].parameters)
2800
2801 self.worker.hold_jobs_in_build = False
2802 self.worker.release()
2803 self.waitUntilSettled()
Joshua Hesketh85af4e92014-02-21 08:28:58 -08002804
2805 def test_client_get_running_jobs(self):
2806 "Test that the RPC client can get a list of running jobs"
2807 self.worker.hold_jobs_in_build = True
2808 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2809 A.addApproval('CRVW', 2)
2810 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2811 self.waitUntilSettled()
2812
2813 client = zuul.rpcclient.RPCClient('127.0.0.1',
2814 self.gearman_server.port)
2815
2816 # Wait for gearman server to send the initial workData back to zuul
2817 start = time.time()
2818 while True:
2819 if time.time() - start > 10:
2820 raise Exception("Timeout waiting for gearman server to report "
2821 + "back to the client")
2822 build = self.launcher.builds.values()[0]
2823 if build.worker.name == "My Worker":
2824 break
2825 else:
2826 time.sleep(0)
2827
2828 running_items = client.get_running_jobs()
2829
2830 self.assertEqual(1, len(running_items))
2831 running_item = running_items[0]
2832 self.assertEqual([], running_item['failing_reasons'])
2833 self.assertEqual([], running_item['items_behind'])
2834 self.assertEqual('https://hostname/1', running_item['url'])
2835 self.assertEqual(None, running_item['item_ahead'])
2836 self.assertEqual('org/project', running_item['project'])
2837 self.assertEqual(None, running_item['remaining_time'])
2838 self.assertEqual(True, running_item['active'])
2839 self.assertEqual('1,1', running_item['id'])
2840
2841 self.assertEqual(3, len(running_item['jobs']))
2842 for job in running_item['jobs']:
2843 if job['name'] == 'project-merge':
2844 self.assertEqual('project-merge', job['name'])
2845 self.assertEqual('gate', job['pipeline'])
2846 self.assertEqual(False, job['retry'])
2847 self.assertEqual(13, len(job['parameters']))
2848 self.assertEqual('https://server/job/project-merge/0/',
2849 job['url'])
2850 self.assertEqual(7, len(job['worker']))
2851 self.assertEqual(False, job['canceled'])
2852 self.assertEqual(True, job['voting'])
2853 self.assertEqual(None, job['result'])
2854 self.assertEqual('gate', job['pipeline'])
2855 break
2856
2857 self.worker.hold_jobs_in_build = False
2858 self.worker.release()
2859 self.waitUntilSettled()
2860
2861 running_items = client.get_running_jobs()
2862 self.assertEqual(0, len(running_items))
James E. Blairbadc1ad2014-04-28 13:55:14 -07002863
2864 def test_nonvoting_pipeline(self):
2865 "Test that a nonvoting pipeline (experimental) can still report"
2866
Joshua Heskethcc017ea2014-04-30 19:55:25 +10002867 A = self.fake_gerrit.addFakeChange('org/experimental-project',
2868 'master', 'A')
James E. Blairbadc1ad2014-04-28 13:55:14 -07002869 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2870 self.waitUntilSettled()
Joshua Heskethcc017ea2014-04-30 19:55:25 +10002871 self.assertEqual(
2872 self.getJobFromHistory('experimental-project-test').result,
2873 'SUCCESS')
James E. Blairbadc1ad2014-04-28 13:55:14 -07002874 self.assertEqual(A.reported, 1)