blob: 6a16b379be7ab8d9ec4ec11028c50d9ab17969fa [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
Maru Newby3fe5f852015-01-13 04:22:14 +000023import yaml
Monty Taylorbc758832013-06-17 17:22:42 -040024
James E. Blair4886cc12012-07-18 15:39:41 -070025import git
Morgan Fainberg293f7f82016-05-30 14:01:22 -070026from six.moves import urllib
Monty Taylorbc758832013-06-17 17:22:42 -040027import testtools
James E. Blairb0fcae42012-07-17 11:12:10 -070028
Maru Newby3fe5f852015-01-13 04:22:14 +000029import zuul.change_matcher
James E. Blairb0fcae42012-07-17 11:12:10 -070030import zuul.scheduler
James E. Blairad28e912013-11-27 10:43:22 -080031import zuul.rpcclient
Joshua Hesketh1879cf72013-08-19 14:13:15 +100032import zuul.reporter.gerrit
Joshua Hesketh5fea8672013-08-19 17:32:01 +100033import zuul.reporter.smtp
James E. Blairb0fcae42012-07-17 11:12:10 -070034
Maru Newby3fe5f852015-01-13 04:22:14 +000035from tests.base import (
Maru Newby3fe5f852015-01-13 04:22:14 +000036 ZuulTestCase,
37 repack_repo,
38)
James E. Blairb0fcae42012-07-17 11:12:10 -070039
James E. Blair1f4c2bb2013-04-26 08:40:46 -070040logging.basicConfig(level=logging.DEBUG,
41 format='%(asctime)s %(name)-32s '
42 '%(levelname)-8s %(message)s')
James E. Blairb0fcae42012-07-17 11:12:10 -070043
44
Clark Boylanb640e052014-04-03 16:41:46 -070045class TestScheduler(ZuulTestCase):
Antoine Mussobd86a312014-01-08 14:51:33 +010046
James E. Blairb0fcae42012-07-17 11:12:10 -070047 def test_jobs_launched(self):
48 "Test that jobs are launched and a change is merged"
James E. Blair1f4c2bb2013-04-26 08:40:46 -070049
James E. Blairb0fcae42012-07-17 11:12:10 -070050 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
James E. Blair8c803f82012-07-31 16:25:42 -070051 A.addApproval('CRVW', 2)
James E. Blairb0fcae42012-07-17 11:12:10 -070052 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
53 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -040054 self.assertEqual(self.getJobFromHistory('project-merge').result,
55 'SUCCESS')
56 self.assertEqual(self.getJobFromHistory('project-test1').result,
57 'SUCCESS')
58 self.assertEqual(self.getJobFromHistory('project-test2').result,
59 'SUCCESS')
60 self.assertEqual(A.data['status'], 'MERGED')
61 self.assertEqual(A.reported, 2)
James E. Blairb0fcae42012-07-17 11:12:10 -070062
James E. Blair66eeebf2013-07-27 17:44:32 -070063 self.assertReportedStat('gerrit.event.comment-added', value='1|c')
64 self.assertReportedStat('zuul.pipeline.gate.current_changes',
65 value='1|g')
66 self.assertReportedStat('zuul.pipeline.gate.job.project-merge.SUCCESS',
67 kind='ms')
68 self.assertReportedStat('zuul.pipeline.gate.job.project-merge.SUCCESS',
69 value='1|c')
70 self.assertReportedStat('zuul.pipeline.gate.resident_time', kind='ms')
71 self.assertReportedStat('zuul.pipeline.gate.total_changes',
72 value='1|c')
James E. Blair412e5582013-04-22 15:50:12 -070073 self.assertReportedStat(
James E. Blair66eeebf2013-07-27 17:44:32 -070074 'zuul.pipeline.gate.org.project.resident_time', kind='ms')
James E. Blair412e5582013-04-22 15:50:12 -070075 self.assertReportedStat(
James E. Blair66eeebf2013-07-27 17:44:32 -070076 'zuul.pipeline.gate.org.project.total_changes', value='1|c')
James E. Blair412e5582013-04-22 15:50:12 -070077
James E. Blair5821bd92015-09-16 08:48:15 -070078 for build in self.builds:
79 self.assertEqual(build.parameters['ZUUL_VOTING'], '1')
80
James E. Blair3cb10702013-08-24 08:56:03 -070081 def test_initial_pipeline_gauges(self):
82 "Test that each pipeline reported its length on start"
83 pipeline_names = self.sched.layout.pipelines.keys()
84 self.assertNotEqual(len(pipeline_names), 0)
85 for name in pipeline_names:
86 self.assertReportedStat('zuul.pipeline.%s.current_changes' % name,
87 value='0|g')
88
James E. Blair42f74822013-05-14 15:18:03 -070089 def test_duplicate_pipelines(self):
90 "Test that a change matching multiple pipelines works"
James E. Blair1b4d9722013-05-21 10:32:04 -070091
James E. Blair42f74822013-05-14 15:18:03 -070092 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
93 self.fake_gerrit.addEvent(A.getChangeRestoredEvent())
94 self.waitUntilSettled()
James E. Blair42f74822013-05-14 15:18:03 -070095
Monty Taylor98f0f3e2013-07-06 16:02:31 -040096 self.assertEqual(len(self.history), 2)
Monty Taylor6bef8ef2013-06-02 08:17:12 -040097 self.history[0].name == 'project-test1'
98 self.history[1].name == 'project-test1'
James E. Blair42f74822013-05-14 15:18:03 -070099
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400100 self.assertEqual(len(A.messages), 2)
James E. Blair42f74822013-05-14 15:18:03 -0700101 if 'dup1/project-test1' in A.messages[0]:
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400102 self.assertIn('dup1/project-test1', A.messages[0])
103 self.assertNotIn('dup2/project-test1', A.messages[0])
104 self.assertNotIn('dup1/project-test1', A.messages[1])
105 self.assertIn('dup2/project-test1', A.messages[1])
James E. Blair42f74822013-05-14 15:18:03 -0700106 else:
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400107 self.assertIn('dup1/project-test1', A.messages[1])
108 self.assertNotIn('dup2/project-test1', A.messages[1])
109 self.assertNotIn('dup1/project-test1', A.messages[0])
110 self.assertIn('dup2/project-test1', A.messages[0])
James E. Blair42f74822013-05-14 15:18:03 -0700111
James E. Blairb0fcae42012-07-17 11:12:10 -0700112 def test_parallel_changes(self):
113 "Test that changes are tested in parallel and merged in series"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700114
115 self.worker.hold_jobs_in_build = True
James E. Blairb0fcae42012-07-17 11:12:10 -0700116 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
117 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
118 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
James E. Blair8c803f82012-07-31 16:25:42 -0700119 A.addApproval('CRVW', 2)
120 B.addApproval('CRVW', 2)
121 C.addApproval('CRVW', 2)
James E. Blairb0fcae42012-07-17 11:12:10 -0700122
123 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
124 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
125 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
126
127 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400128 self.assertEqual(len(self.builds), 1)
129 self.assertEqual(self.builds[0].name, 'project-merge')
130 self.assertTrue(self.job_has_changes(self.builds[0], A))
James E. Blairb0fcae42012-07-17 11:12:10 -0700131
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700132 self.worker.release('.*-merge')
James E. Blairb0fcae42012-07-17 11:12:10 -0700133 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400134 self.assertEqual(len(self.builds), 3)
135 self.assertEqual(self.builds[0].name, 'project-test1')
136 self.assertTrue(self.job_has_changes(self.builds[0], A))
137 self.assertEqual(self.builds[1].name, 'project-test2')
138 self.assertTrue(self.job_has_changes(self.builds[1], A))
139 self.assertEqual(self.builds[2].name, 'project-merge')
140 self.assertTrue(self.job_has_changes(self.builds[2], A, B))
James E. Blairb0fcae42012-07-17 11:12:10 -0700141
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700142 self.worker.release('.*-merge')
James E. Blairb0fcae42012-07-17 11:12:10 -0700143 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400144 self.assertEqual(len(self.builds), 5)
145 self.assertEqual(self.builds[0].name, 'project-test1')
146 self.assertTrue(self.job_has_changes(self.builds[0], A))
147 self.assertEqual(self.builds[1].name, 'project-test2')
148 self.assertTrue(self.job_has_changes(self.builds[1], A))
James E. Blairb0fcae42012-07-17 11:12:10 -0700149
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400150 self.assertEqual(self.builds[2].name, 'project-test1')
151 self.assertTrue(self.job_has_changes(self.builds[2], A, B))
152 self.assertEqual(self.builds[3].name, 'project-test2')
153 self.assertTrue(self.job_has_changes(self.builds[3], A, B))
James E. Blairb0fcae42012-07-17 11:12:10 -0700154
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400155 self.assertEqual(self.builds[4].name, 'project-merge')
156 self.assertTrue(self.job_has_changes(self.builds[4], A, B, C))
James E. Blairb0fcae42012-07-17 11:12:10 -0700157
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700158 self.worker.release('.*-merge')
James E. Blairb0fcae42012-07-17 11:12:10 -0700159 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400160 self.assertEqual(len(self.builds), 6)
161 self.assertEqual(self.builds[0].name, 'project-test1')
162 self.assertTrue(self.job_has_changes(self.builds[0], A))
163 self.assertEqual(self.builds[1].name, 'project-test2')
164 self.assertTrue(self.job_has_changes(self.builds[1], A))
James E. Blairb0fcae42012-07-17 11:12:10 -0700165
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400166 self.assertEqual(self.builds[2].name, 'project-test1')
167 self.assertTrue(self.job_has_changes(self.builds[2], A, B))
168 self.assertEqual(self.builds[3].name, 'project-test2')
169 self.assertTrue(self.job_has_changes(self.builds[3], A, B))
James E. Blairb0fcae42012-07-17 11:12:10 -0700170
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400171 self.assertEqual(self.builds[4].name, 'project-test1')
172 self.assertTrue(self.job_has_changes(self.builds[4], A, B, C))
173 self.assertEqual(self.builds[5].name, 'project-test2')
174 self.assertTrue(self.job_has_changes(self.builds[5], A, B, C))
James E. Blairb0fcae42012-07-17 11:12:10 -0700175
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700176 self.worker.hold_jobs_in_build = False
177 self.worker.release()
James E. Blairb0fcae42012-07-17 11:12:10 -0700178 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400179 self.assertEqual(len(self.builds), 0)
James E. Blairb0fcae42012-07-17 11:12:10 -0700180
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400181 self.assertEqual(len(self.history), 9)
182 self.assertEqual(A.data['status'], 'MERGED')
183 self.assertEqual(B.data['status'], 'MERGED')
184 self.assertEqual(C.data['status'], 'MERGED')
185 self.assertEqual(A.reported, 2)
186 self.assertEqual(B.reported, 2)
187 self.assertEqual(C.reported, 2)
James E. Blairb02a3bb2012-07-30 17:49:55 -0700188
189 def test_failed_changes(self):
190 "Test that a change behind a failed change is retested"
James E. Blaire2819012013-06-28 17:17:26 -0400191 self.worker.hold_jobs_in_build = True
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700192
James E. Blairb02a3bb2012-07-30 17:49:55 -0700193 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
194 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
James E. Blair8c803f82012-07-31 16:25:42 -0700195 A.addApproval('CRVW', 2)
196 B.addApproval('CRVW', 2)
James E. Blairb02a3bb2012-07-30 17:49:55 -0700197
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700198 self.worker.addFailTest('project-test1', A)
James E. Blairb02a3bb2012-07-30 17:49:55 -0700199
James E. Blaire2819012013-06-28 17:17:26 -0400200 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
201 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
James E. Blairb02a3bb2012-07-30 17:49:55 -0700202 self.waitUntilSettled()
James E. Blaire2819012013-06-28 17:17:26 -0400203
204 self.worker.release('.*-merge')
205 self.waitUntilSettled()
206
207 self.worker.hold_jobs_in_build = False
208 self.worker.release()
209
210 self.waitUntilSettled()
211 # It's certain that the merge job for change 2 will run, but
212 # the test1 and test2 jobs may or may not run.
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400213 self.assertTrue(len(self.history) > 6)
214 self.assertEqual(A.data['status'], 'NEW')
215 self.assertEqual(B.data['status'], 'MERGED')
216 self.assertEqual(A.reported, 2)
217 self.assertEqual(B.reported, 2)
James E. Blairb02a3bb2012-07-30 17:49:55 -0700218
219 def test_independent_queues(self):
220 "Test that changes end up in the right queues"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700221
222 self.worker.hold_jobs_in_build = True
Zhongyue Luo5d556072012-09-21 02:00:47 +0900223 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
James E. Blairb02a3bb2012-07-30 17:49:55 -0700224 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
225 C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
James E. Blair8c803f82012-07-31 16:25:42 -0700226 A.addApproval('CRVW', 2)
227 B.addApproval('CRVW', 2)
228 C.addApproval('CRVW', 2)
James E. Blairb02a3bb2012-07-30 17:49:55 -0700229
230 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
231 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
232 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
233
James E. Blairb02a3bb2012-07-30 17:49:55 -0700234 self.waitUntilSettled()
235
236 # There should be one merge job at the head of each queue running
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400237 self.assertEqual(len(self.builds), 2)
238 self.assertEqual(self.builds[0].name, 'project-merge')
239 self.assertTrue(self.job_has_changes(self.builds[0], A))
240 self.assertEqual(self.builds[1].name, 'project1-merge')
241 self.assertTrue(self.job_has_changes(self.builds[1], B))
James E. Blairb02a3bb2012-07-30 17:49:55 -0700242
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700243 # Release the current merge builds
244 self.worker.release('.*-merge')
James E. Blairb02a3bb2012-07-30 17:49:55 -0700245 self.waitUntilSettled()
246 # Release the merge job for project2 which is behind project1
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700247 self.worker.release('.*-merge')
James E. Blairb02a3bb2012-07-30 17:49:55 -0700248 self.waitUntilSettled()
249
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700250 # All the test builds should be running:
James E. Blairb02a3bb2012-07-30 17:49:55 -0700251 # project1 (3) + project2 (3) + project (2) = 8
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400252 self.assertEqual(len(self.builds), 8)
James E. Blairb02a3bb2012-07-30 17:49:55 -0700253
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700254 self.worker.release()
James E. Blairb02a3bb2012-07-30 17:49:55 -0700255 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400256 self.assertEqual(len(self.builds), 0)
James E. Blairb02a3bb2012-07-30 17:49:55 -0700257
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400258 self.assertEqual(len(self.history), 11)
259 self.assertEqual(A.data['status'], 'MERGED')
260 self.assertEqual(B.data['status'], 'MERGED')
261 self.assertEqual(C.data['status'], 'MERGED')
262 self.assertEqual(A.reported, 2)
263 self.assertEqual(B.reported, 2)
264 self.assertEqual(C.reported, 2)
James E. Blaird466dc42012-07-31 10:42:56 -0700265
266 def test_failed_change_at_head(self):
267 "Test that if a change at the head fails, jobs behind it are canceled"
James E. Blaird466dc42012-07-31 10:42:56 -0700268
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700269 self.worker.hold_jobs_in_build = True
James E. Blaird466dc42012-07-31 10:42:56 -0700270 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
271 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
272 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
James E. Blair8c803f82012-07-31 16:25:42 -0700273 A.addApproval('CRVW', 2)
274 B.addApproval('CRVW', 2)
275 C.addApproval('CRVW', 2)
James E. Blaird466dc42012-07-31 10:42:56 -0700276
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700277 self.worker.addFailTest('project-test1', A)
James E. Blaird466dc42012-07-31 10:42:56 -0700278
279 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
280 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
281 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
282
283 self.waitUntilSettled()
James E. Blaird466dc42012-07-31 10:42:56 -0700284
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400285 self.assertEqual(len(self.builds), 1)
286 self.assertEqual(self.builds[0].name, 'project-merge')
287 self.assertTrue(self.job_has_changes(self.builds[0], A))
James E. Blaird466dc42012-07-31 10:42:56 -0700288
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700289 self.worker.release('.*-merge')
James E. Blaird466dc42012-07-31 10:42:56 -0700290 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700291 self.worker.release('.*-merge')
James E. Blaird466dc42012-07-31 10:42:56 -0700292 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700293 self.worker.release('.*-merge')
James E. Blaird466dc42012-07-31 10:42:56 -0700294 self.waitUntilSettled()
295
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400296 self.assertEqual(len(self.builds), 6)
297 self.assertEqual(self.builds[0].name, 'project-test1')
298 self.assertEqual(self.builds[1].name, 'project-test2')
299 self.assertEqual(self.builds[2].name, 'project-test1')
300 self.assertEqual(self.builds[3].name, 'project-test2')
301 self.assertEqual(self.builds[4].name, 'project-test1')
302 self.assertEqual(self.builds[5].name, 'project-test2')
James E. Blaird466dc42012-07-31 10:42:56 -0700303
Monty Taylor6bef8ef2013-06-02 08:17:12 -0400304 self.release(self.builds[0])
James E. Blaird466dc42012-07-31 10:42:56 -0700305 self.waitUntilSettled()
306
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400307 # project-test2, project-merge for B
308 self.assertEqual(len(self.builds), 2)
309 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 4)
James E. Blaird466dc42012-07-31 10:42:56 -0700310
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700311 self.worker.hold_jobs_in_build = False
312 self.worker.release()
James E. Blaird466dc42012-07-31 10:42:56 -0700313 self.waitUntilSettled()
314
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400315 self.assertEqual(len(self.builds), 0)
316 self.assertEqual(len(self.history), 15)
317 self.assertEqual(A.data['status'], 'NEW')
318 self.assertEqual(B.data['status'], 'MERGED')
319 self.assertEqual(C.data['status'], 'MERGED')
320 self.assertEqual(A.reported, 2)
321 self.assertEqual(B.reported, 2)
322 self.assertEqual(C.reported, 2)
James E. Blaird466dc42012-07-31 10:42:56 -0700323
James E. Blair0aac4872013-08-23 14:02:38 -0700324 def test_failed_change_in_middle(self):
325 "Test a failed change in the middle of the queue"
326
327 self.worker.hold_jobs_in_build = True
328 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
329 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
330 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
331 A.addApproval('CRVW', 2)
332 B.addApproval('CRVW', 2)
333 C.addApproval('CRVW', 2)
334
335 self.worker.addFailTest('project-test1', B)
336
337 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
338 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
339 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
340
341 self.waitUntilSettled()
342
343 self.worker.release('.*-merge')
344 self.waitUntilSettled()
345 self.worker.release('.*-merge')
346 self.waitUntilSettled()
347 self.worker.release('.*-merge')
348 self.waitUntilSettled()
349
350 self.assertEqual(len(self.builds), 6)
351 self.assertEqual(self.builds[0].name, 'project-test1')
352 self.assertEqual(self.builds[1].name, 'project-test2')
353 self.assertEqual(self.builds[2].name, 'project-test1')
354 self.assertEqual(self.builds[3].name, 'project-test2')
355 self.assertEqual(self.builds[4].name, 'project-test1')
356 self.assertEqual(self.builds[5].name, 'project-test2')
357
358 self.release(self.builds[2])
359 self.waitUntilSettled()
360
James E. Blair972e3c72013-08-29 12:04:55 -0700361 # project-test1 and project-test2 for A
362 # project-test2 for B
363 # project-merge for C (without B)
364 self.assertEqual(len(self.builds), 4)
James E. Blair0aac4872013-08-23 14:02:38 -0700365 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 2)
366
James E. Blair972e3c72013-08-29 12:04:55 -0700367 self.worker.release('.*-merge')
368 self.waitUntilSettled()
369
370 # project-test1 and project-test2 for A
371 # project-test2 for B
372 # project-test1 and project-test2 for C
373 self.assertEqual(len(self.builds), 5)
374
James E. Blair0aac4872013-08-23 14:02:38 -0700375 items = self.sched.layout.pipelines['gate'].getAllItems()
376 builds = items[0].current_build_set.getBuilds()
377 self.assertEqual(self.countJobResults(builds, 'SUCCESS'), 1)
378 self.assertEqual(self.countJobResults(builds, None), 2)
379 builds = items[1].current_build_set.getBuilds()
380 self.assertEqual(self.countJobResults(builds, 'SUCCESS'), 1)
381 self.assertEqual(self.countJobResults(builds, 'FAILURE'), 1)
382 self.assertEqual(self.countJobResults(builds, None), 1)
383 builds = items[2].current_build_set.getBuilds()
384 self.assertEqual(self.countJobResults(builds, 'SUCCESS'), 1)
James E. Blair972e3c72013-08-29 12:04:55 -0700385 self.assertEqual(self.countJobResults(builds, None), 2)
James E. Blair0aac4872013-08-23 14:02:38 -0700386
387 self.worker.hold_jobs_in_build = False
388 self.worker.release()
389 self.waitUntilSettled()
390
391 self.assertEqual(len(self.builds), 0)
392 self.assertEqual(len(self.history), 12)
393 self.assertEqual(A.data['status'], 'MERGED')
394 self.assertEqual(B.data['status'], 'NEW')
395 self.assertEqual(C.data['status'], 'MERGED')
396 self.assertEqual(A.reported, 2)
397 self.assertEqual(B.reported, 2)
398 self.assertEqual(C.reported, 2)
399
James E. Blaird466dc42012-07-31 10:42:56 -0700400 def test_failed_change_at_head_with_queue(self):
401 "Test that if a change at the head fails, queued jobs are canceled"
James E. Blaird466dc42012-07-31 10:42:56 -0700402
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700403 self.gearman_server.hold_jobs_in_queue = True
James E. Blaird466dc42012-07-31 10:42:56 -0700404 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
405 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
406 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
James E. Blair8c803f82012-07-31 16:25:42 -0700407 A.addApproval('CRVW', 2)
408 B.addApproval('CRVW', 2)
409 C.addApproval('CRVW', 2)
James E. Blaird466dc42012-07-31 10:42:56 -0700410
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700411 self.worker.addFailTest('project-test1', A)
James E. Blaird466dc42012-07-31 10:42:56 -0700412
413 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
414 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
415 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
416
417 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -0700418 queue = self.gearman_server.getQueue()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400419 self.assertEqual(len(self.builds), 0)
420 self.assertEqual(len(queue), 1)
421 self.assertEqual(queue[0].name, 'build:project-merge')
422 self.assertTrue(self.job_has_changes(queue[0], A))
James E. Blaird466dc42012-07-31 10:42:56 -0700423
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700424 self.gearman_server.release('.*-merge')
James E. Blaird466dc42012-07-31 10:42:56 -0700425 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700426 self.gearman_server.release('.*-merge')
James E. Blaird466dc42012-07-31 10:42:56 -0700427 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700428 self.gearman_server.release('.*-merge')
James E. Blaird466dc42012-07-31 10:42:56 -0700429 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -0700430 queue = self.gearman_server.getQueue()
James E. Blaird466dc42012-07-31 10:42:56 -0700431
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400432 self.assertEqual(len(self.builds), 0)
433 self.assertEqual(len(queue), 6)
434 self.assertEqual(queue[0].name, 'build:project-test1')
435 self.assertEqual(queue[1].name, 'build:project-test2')
436 self.assertEqual(queue[2].name, 'build:project-test1')
437 self.assertEqual(queue[3].name, 'build:project-test2')
438 self.assertEqual(queue[4].name, 'build:project-test1')
439 self.assertEqual(queue[5].name, 'build:project-test2')
James E. Blaird466dc42012-07-31 10:42:56 -0700440
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700441 self.release(queue[0])
James E. Blaird466dc42012-07-31 10:42:56 -0700442 self.waitUntilSettled()
443
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400444 self.assertEqual(len(self.builds), 0)
James E. Blair701c5b42013-06-06 09:34:59 -0700445 queue = self.gearman_server.getQueue()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400446 self.assertEqual(len(queue), 2) # project-test2, project-merge for B
447 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 0)
James E. Blaird466dc42012-07-31 10:42:56 -0700448
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700449 self.gearman_server.hold_jobs_in_queue = False
450 self.gearman_server.release()
James E. Blaird466dc42012-07-31 10:42:56 -0700451 self.waitUntilSettled()
452
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400453 self.assertEqual(len(self.builds), 0)
454 self.assertEqual(len(self.history), 11)
455 self.assertEqual(A.data['status'], 'NEW')
456 self.assertEqual(B.data['status'], 'MERGED')
457 self.assertEqual(C.data['status'], 'MERGED')
458 self.assertEqual(A.reported, 2)
459 self.assertEqual(B.reported, 2)
460 self.assertEqual(C.reported, 2)
James E. Blair8c803f82012-07-31 16:25:42 -0700461
James E. Blairce8a2132016-05-19 15:21:52 -0700462 def _test_time_database(self, iteration):
463 self.worker.hold_jobs_in_build = True
464 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
465 A.addApproval('CRVW', 2)
466 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
467 self.waitUntilSettled()
468 time.sleep(2)
469
470 data = json.loads(self.sched.formatStatusJSON())
471 found_job = None
472 for pipeline in data['pipelines']:
473 if pipeline['name'] != 'gate':
474 continue
475 for queue in pipeline['change_queues']:
476 for head in queue['heads']:
477 for item in head:
478 for job in item['jobs']:
479 if job['name'] == 'project-merge':
480 found_job = job
481 break
482
483 self.assertIsNotNone(found_job)
484 if iteration == 1:
485 self.assertIsNotNone(found_job['estimated_time'])
486 self.assertIsNone(found_job['remaining_time'])
487 else:
488 self.assertIsNotNone(found_job['estimated_time'])
489 self.assertTrue(found_job['estimated_time'] >= 2)
490 self.assertIsNotNone(found_job['remaining_time'])
491
492 self.worker.hold_jobs_in_build = False
493 self.worker.release()
494 self.waitUntilSettled()
495
496 def test_time_database(self):
497 "Test the time database"
498
499 self._test_time_database(1)
500 self._test_time_database(2)
501
James E. Blairfef71632013-09-23 11:15:47 -0700502 def test_two_failed_changes_at_head(self):
503 "Test that changes are reparented correctly if 2 fail at head"
504
505 self.worker.hold_jobs_in_build = True
506 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
507 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
508 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
509 A.addApproval('CRVW', 2)
510 B.addApproval('CRVW', 2)
511 C.addApproval('CRVW', 2)
512
513 self.worker.addFailTest('project-test1', A)
514 self.worker.addFailTest('project-test1', B)
515
516 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
517 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
518 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
519 self.waitUntilSettled()
520
521 self.worker.release('.*-merge')
522 self.waitUntilSettled()
523 self.worker.release('.*-merge')
524 self.waitUntilSettled()
525 self.worker.release('.*-merge')
526 self.waitUntilSettled()
527
528 self.assertEqual(len(self.builds), 6)
529 self.assertEqual(self.builds[0].name, 'project-test1')
530 self.assertEqual(self.builds[1].name, 'project-test2')
531 self.assertEqual(self.builds[2].name, 'project-test1')
532 self.assertEqual(self.builds[3].name, 'project-test2')
533 self.assertEqual(self.builds[4].name, 'project-test1')
534 self.assertEqual(self.builds[5].name, 'project-test2')
535
536 self.assertTrue(self.job_has_changes(self.builds[0], A))
537 self.assertTrue(self.job_has_changes(self.builds[2], A))
538 self.assertTrue(self.job_has_changes(self.builds[2], B))
539 self.assertTrue(self.job_has_changes(self.builds[4], A))
540 self.assertTrue(self.job_has_changes(self.builds[4], B))
541 self.assertTrue(self.job_has_changes(self.builds[4], C))
542
543 # Fail change B first
544 self.release(self.builds[2])
545 self.waitUntilSettled()
546
547 # restart of C after B failure
548 self.worker.release('.*-merge')
549 self.waitUntilSettled()
550
551 self.assertEqual(len(self.builds), 5)
552 self.assertEqual(self.builds[0].name, 'project-test1')
553 self.assertEqual(self.builds[1].name, 'project-test2')
554 self.assertEqual(self.builds[2].name, 'project-test2')
555 self.assertEqual(self.builds[3].name, 'project-test1')
556 self.assertEqual(self.builds[4].name, 'project-test2')
557
558 self.assertTrue(self.job_has_changes(self.builds[1], A))
559 self.assertTrue(self.job_has_changes(self.builds[2], A))
560 self.assertTrue(self.job_has_changes(self.builds[2], B))
561 self.assertTrue(self.job_has_changes(self.builds[4], A))
562 self.assertFalse(self.job_has_changes(self.builds[4], B))
563 self.assertTrue(self.job_has_changes(self.builds[4], C))
564
565 # Finish running all passing jobs for change A
566 self.release(self.builds[1])
567 self.waitUntilSettled()
568 # Fail and report change A
569 self.release(self.builds[0])
570 self.waitUntilSettled()
571
572 # restart of B,C after A failure
573 self.worker.release('.*-merge')
574 self.waitUntilSettled()
575 self.worker.release('.*-merge')
576 self.waitUntilSettled()
577
578 self.assertEqual(len(self.builds), 4)
579 self.assertEqual(self.builds[0].name, 'project-test1') # B
580 self.assertEqual(self.builds[1].name, 'project-test2') # B
581 self.assertEqual(self.builds[2].name, 'project-test1') # C
582 self.assertEqual(self.builds[3].name, 'project-test2') # C
583
584 self.assertFalse(self.job_has_changes(self.builds[1], A))
585 self.assertTrue(self.job_has_changes(self.builds[1], B))
586 self.assertFalse(self.job_has_changes(self.builds[1], C))
587
588 self.assertFalse(self.job_has_changes(self.builds[2], A))
589 # After A failed and B and C restarted, B should be back in
590 # C's tests because it has not failed yet.
591 self.assertTrue(self.job_has_changes(self.builds[2], B))
592 self.assertTrue(self.job_has_changes(self.builds[2], C))
593
594 self.worker.hold_jobs_in_build = False
595 self.worker.release()
596 self.waitUntilSettled()
597
598 self.assertEqual(len(self.builds), 0)
599 self.assertEqual(len(self.history), 21)
600 self.assertEqual(A.data['status'], 'NEW')
601 self.assertEqual(B.data['status'], 'NEW')
602 self.assertEqual(C.data['status'], 'MERGED')
603 self.assertEqual(A.reported, 2)
604 self.assertEqual(B.reported, 2)
605 self.assertEqual(C.reported, 2)
606
James E. Blairce8a2132016-05-19 15:21:52 -0700607 def test_parse_skip_if(self):
608 job_yaml = """
609jobs:
610 - name: job_name
611 skip-if:
612 - project: ^project_name$
613 branch: ^stable/icehouse$
614 all-files-match-any:
615 - ^filename$
616 - project: ^project2_name$
617 all-files-match-any:
618 - ^filename2$
619 """.strip()
620 data = yaml.load(job_yaml)
621 config_job = data.get('jobs')[0]
622 cm = zuul.change_matcher
623 expected = cm.MatchAny([
624 cm.MatchAll([
625 cm.ProjectMatcher('^project_name$'),
626 cm.BranchMatcher('^stable/icehouse$'),
627 cm.MatchAllFiles([cm.FileMatcher('^filename$')]),
628 ]),
629 cm.MatchAll([
630 cm.ProjectMatcher('^project2_name$'),
631 cm.MatchAllFiles([cm.FileMatcher('^filename2$')]),
632 ]),
633 ])
634 matcher = self.sched._parseSkipIf(config_job)
635 self.assertEqual(expected, matcher)
636
James E. Blair8c803f82012-07-31 16:25:42 -0700637 def test_patch_order(self):
638 "Test that dependent patches are tested in the right order"
639 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
640 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
641 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
642 A.addApproval('CRVW', 2)
643 B.addApproval('CRVW', 2)
644 C.addApproval('CRVW', 2)
645
646 M2 = self.fake_gerrit.addFakeChange('org/project', 'master', 'M2')
647 M1 = self.fake_gerrit.addFakeChange('org/project', 'master', 'M1')
648 M2.setMerged()
649 M1.setMerged()
650
651 # C -> B -> A -> M1 -> M2
652 # M2 is here to make sure it is never queried. If it is, it
653 # means zuul is walking down the entire history of merged
654 # changes.
655
656 C.setDependsOn(B, 1)
657 B.setDependsOn(A, 1)
658 A.setDependsOn(M1, 1)
659 M1.setDependsOn(M2, 1)
660
661 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
662
663 self.waitUntilSettled()
664
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400665 self.assertEqual(A.data['status'], 'NEW')
666 self.assertEqual(B.data['status'], 'NEW')
667 self.assertEqual(C.data['status'], 'NEW')
James E. Blair8c803f82012-07-31 16:25:42 -0700668
669 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
670 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
671
672 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400673 self.assertEqual(M2.queried, 0)
674 self.assertEqual(A.data['status'], 'MERGED')
675 self.assertEqual(B.data['status'], 'MERGED')
676 self.assertEqual(C.data['status'], 'MERGED')
677 self.assertEqual(A.reported, 2)
678 self.assertEqual(B.reported, 2)
679 self.assertEqual(C.reported, 2)
James E. Blair8c803f82012-07-31 16:25:42 -0700680
James E. Blair063672f2015-01-29 13:09:12 -0800681 def test_needed_changes_enqueue(self):
682 "Test that a needed change is enqueued ahead"
683 # A Given a git tree like this, if we enqueue
684 # / \ change C, we should walk up and down the tree
685 # B G and enqueue changes in the order ABCDEFG.
686 # /|\ This is also the order that you would get if
687 # *C E F you enqueued changes in the order ABCDEFG, so
688 # / the ordering is stable across re-enqueue events.
689 # D
690
691 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
692 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
693 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
694 D = self.fake_gerrit.addFakeChange('org/project', 'master', 'D')
695 E = self.fake_gerrit.addFakeChange('org/project', 'master', 'E')
696 F = self.fake_gerrit.addFakeChange('org/project', 'master', 'F')
697 G = self.fake_gerrit.addFakeChange('org/project', 'master', 'G')
698 B.setDependsOn(A, 1)
699 C.setDependsOn(B, 1)
700 D.setDependsOn(C, 1)
701 E.setDependsOn(B, 1)
702 F.setDependsOn(B, 1)
703 G.setDependsOn(A, 1)
704
705 A.addApproval('CRVW', 2)
706 B.addApproval('CRVW', 2)
707 C.addApproval('CRVW', 2)
708 D.addApproval('CRVW', 2)
709 E.addApproval('CRVW', 2)
710 F.addApproval('CRVW', 2)
711 G.addApproval('CRVW', 2)
712 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
713
714 self.waitUntilSettled()
715
716 self.assertEqual(A.data['status'], 'NEW')
717 self.assertEqual(B.data['status'], 'NEW')
718 self.assertEqual(C.data['status'], 'NEW')
719 self.assertEqual(D.data['status'], 'NEW')
720 self.assertEqual(E.data['status'], 'NEW')
721 self.assertEqual(F.data['status'], 'NEW')
722 self.assertEqual(G.data['status'], 'NEW')
723
724 # We're about to add approvals to changes without adding the
725 # triggering events to Zuul, so that we can be sure that it is
726 # enqueing the changes based on dependencies, not because of
727 # triggering events. Since it will have the changes cached
728 # already (without approvals), we need to clear the cache
729 # first.
Joshua Hesketh4bd7da32016-02-17 20:58:47 +1100730 for connection in self.connections.values():
731 connection.maintainCache([])
James E. Blair063672f2015-01-29 13:09:12 -0800732
733 self.worker.hold_jobs_in_build = True
734 A.addApproval('APRV', 1)
735 B.addApproval('APRV', 1)
736 D.addApproval('APRV', 1)
737 E.addApproval('APRV', 1)
738 F.addApproval('APRV', 1)
739 G.addApproval('APRV', 1)
740 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
741
742 for x in range(8):
743 self.worker.release('.*-merge')
744 self.waitUntilSettled()
745 self.worker.hold_jobs_in_build = False
746 self.worker.release()
747 self.waitUntilSettled()
748
749 self.assertEqual(A.data['status'], 'MERGED')
750 self.assertEqual(B.data['status'], 'MERGED')
751 self.assertEqual(C.data['status'], 'MERGED')
752 self.assertEqual(D.data['status'], 'MERGED')
753 self.assertEqual(E.data['status'], 'MERGED')
754 self.assertEqual(F.data['status'], 'MERGED')
755 self.assertEqual(G.data['status'], 'MERGED')
756 self.assertEqual(A.reported, 2)
757 self.assertEqual(B.reported, 2)
758 self.assertEqual(C.reported, 2)
759 self.assertEqual(D.reported, 2)
760 self.assertEqual(E.reported, 2)
761 self.assertEqual(F.reported, 2)
762 self.assertEqual(G.reported, 2)
763 self.assertEqual(self.history[6].changes,
764 '1,1 2,1 3,1 4,1 5,1 6,1 7,1')
765
Joshua Hesketh850ccb62014-11-27 11:31:02 +1100766 def test_source_cache(self):
767 "Test that the source cache operates correctly"
James E. Blair0e933c52013-07-11 10:18:52 -0700768 self.worker.hold_jobs_in_build = True
769
770 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
771 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
772 X = self.fake_gerrit.addFakeChange('org/project', 'master', 'X')
773 A.addApproval('CRVW', 2)
774 B.addApproval('CRVW', 2)
775
776 M1 = self.fake_gerrit.addFakeChange('org/project', 'master', 'M1')
777 M1.setMerged()
778
779 B.setDependsOn(A, 1)
780 A.setDependsOn(M1, 1)
781
782 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
783 self.fake_gerrit.addEvent(X.getPatchsetCreatedEvent(1))
784
785 self.waitUntilSettled()
786
787 for build in self.builds:
788 if build.parameters['ZUUL_PIPELINE'] == 'check':
789 build.release()
790 self.waitUntilSettled()
791 for build in self.builds:
792 if build.parameters['ZUUL_PIPELINE'] == 'check':
793 build.release()
794 self.waitUntilSettled()
795
796 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
797 self.waitUntilSettled()
798
Joshua Hesketh352264b2015-08-11 23:42:08 +1000799 self.log.debug("len %s" % self.fake_gerrit._change_cache.keys())
James E. Blair0e933c52013-07-11 10:18:52 -0700800 # there should still be changes in the cache
Joshua Hesketh352264b2015-08-11 23:42:08 +1000801 self.assertNotEqual(len(self.fake_gerrit._change_cache.keys()), 0)
James E. Blair0e933c52013-07-11 10:18:52 -0700802
803 self.worker.hold_jobs_in_build = False
804 self.worker.release()
805 self.waitUntilSettled()
806
807 self.assertEqual(A.data['status'], 'MERGED')
808 self.assertEqual(B.data['status'], 'MERGED')
809 self.assertEqual(A.queried, 2) # Initial and isMerged
810 self.assertEqual(B.queried, 3) # Initial A, refresh from B, isMerged
811
James E. Blair8c803f82012-07-31 16:25:42 -0700812 def test_can_merge(self):
James E. Blair4886cc12012-07-18 15:39:41 -0700813 "Test whether a change is ready to merge"
James E. Blair8c803f82012-07-31 16:25:42 -0700814 # TODO: move to test_gerrit (this is a unit test!)
815 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
James E. Blairc0dedf82014-08-06 09:37:52 -0700816 source = self.sched.layout.pipelines['gate'].source
817 a = source._getChange(1, 2)
James E. Blaireff88162013-07-01 12:44:14 -0400818 mgr = self.sched.layout.pipelines['gate'].manager
James E. Blairc0dedf82014-08-06 09:37:52 -0700819 self.assertFalse(source.canMerge(a, mgr.getSubmitAllowNeeds()))
James E. Blair8c803f82012-07-31 16:25:42 -0700820
821 A.addApproval('CRVW', 2)
James E. Blairc0dedf82014-08-06 09:37:52 -0700822 a = source._getChange(1, 2, refresh=True)
823 self.assertFalse(source.canMerge(a, mgr.getSubmitAllowNeeds()))
James E. Blair8c803f82012-07-31 16:25:42 -0700824
825 A.addApproval('APRV', 1)
James E. Blairc0dedf82014-08-06 09:37:52 -0700826 a = source._getChange(1, 2, refresh=True)
827 self.assertTrue(source.canMerge(a, mgr.getSubmitAllowNeeds()))
James E. Blair4886cc12012-07-18 15:39:41 -0700828
829 def test_build_configuration(self):
830 "Test that zuul merges the right commits for testing"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700831
832 self.gearman_server.hold_jobs_in_queue = True
James E. Blair4886cc12012-07-18 15:39:41 -0700833 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
834 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
835 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
836 A.addApproval('CRVW', 2)
837 B.addApproval('CRVW', 2)
838 C.addApproval('CRVW', 2)
839 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
840 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
841 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
842 self.waitUntilSettled()
843
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700844 self.gearman_server.release('.*-merge')
James E. Blair4886cc12012-07-18 15:39:41 -0700845 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700846 self.gearman_server.release('.*-merge')
James E. Blair4886cc12012-07-18 15:39:41 -0700847 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700848 self.gearman_server.release('.*-merge')
James E. Blair4886cc12012-07-18 15:39:41 -0700849 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -0700850 queue = self.gearman_server.getQueue()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700851 ref = self.getParameter(queue[-1], 'ZUUL_REF')
852 self.gearman_server.hold_jobs_in_queue = False
853 self.gearman_server.release()
James E. Blair973721f2012-08-15 10:19:43 -0700854 self.waitUntilSettled()
James E. Blair4886cc12012-07-18 15:39:41 -0700855
Monty Taylorbc758832013-06-17 17:22:42 -0400856 path = os.path.join(self.git_root, "org/project")
James E. Blair4886cc12012-07-18 15:39:41 -0700857 repo = git.Repo(path)
858 repo_messages = [c.message.strip() for c in repo.iter_commits(ref)]
859 repo_messages.reverse()
James E. Blair4886cc12012-07-18 15:39:41 -0700860 correct_messages = ['initial commit', 'A-1', 'B-1', 'C-1']
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400861 self.assertEqual(repo_messages, correct_messages)
James E. Blair973721f2012-08-15 10:19:43 -0700862
863 def test_build_configuration_conflict(self):
864 "Test that merge conflicts are handled"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700865
866 self.gearman_server.hold_jobs_in_queue = True
James E. Blair6736beb2013-07-11 15:18:15 -0700867 A = self.fake_gerrit.addFakeChange('org/conflict-project',
868 'master', 'A')
James E. Blair973721f2012-08-15 10:19:43 -0700869 A.addPatchset(['conflict'])
James E. Blair6736beb2013-07-11 15:18:15 -0700870 B = self.fake_gerrit.addFakeChange('org/conflict-project',
871 'master', 'B')
James E. Blair973721f2012-08-15 10:19:43 -0700872 B.addPatchset(['conflict'])
James E. Blair6736beb2013-07-11 15:18:15 -0700873 C = self.fake_gerrit.addFakeChange('org/conflict-project',
874 'master', 'C')
James E. Blair973721f2012-08-15 10:19:43 -0700875 A.addApproval('CRVW', 2)
876 B.addApproval('CRVW', 2)
877 C.addApproval('CRVW', 2)
878 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
879 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
880 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
881 self.waitUntilSettled()
882
James E. Blair6736beb2013-07-11 15:18:15 -0700883 self.assertEqual(A.reported, 1)
884 self.assertEqual(B.reported, 1)
885 self.assertEqual(C.reported, 1)
886
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700887 self.gearman_server.release('.*-merge')
James E. Blair973721f2012-08-15 10:19:43 -0700888 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700889 self.gearman_server.release('.*-merge')
James E. Blair973721f2012-08-15 10:19:43 -0700890 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700891 self.gearman_server.release('.*-merge')
James E. Blair973721f2012-08-15 10:19:43 -0700892 self.waitUntilSettled()
James E. Blair972e3c72013-08-29 12:04:55 -0700893
894 self.assertEqual(len(self.history), 2) # A and C merge jobs
895
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700896 self.gearman_server.hold_jobs_in_queue = False
897 self.gearman_server.release()
James E. Blair973721f2012-08-15 10:19:43 -0700898 self.waitUntilSettled()
899
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400900 self.assertEqual(A.data['status'], 'MERGED')
901 self.assertEqual(B.data['status'], 'NEW')
902 self.assertEqual(C.data['status'], 'MERGED')
903 self.assertEqual(A.reported, 2)
904 self.assertEqual(B.reported, 2)
905 self.assertEqual(C.reported, 2)
James E. Blair972e3c72013-08-29 12:04:55 -0700906 self.assertEqual(len(self.history), 6)
James E. Blair6736beb2013-07-11 15:18:15 -0700907
James E. Blairdaabed22012-08-15 15:38:57 -0700908 def test_post(self):
909 "Test that post jobs run"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700910
Zhongyue Luo5d556072012-09-21 02:00:47 +0900911 e = {
912 "type": "ref-updated",
913 "submitter": {
914 "name": "User Name",
915 },
916 "refUpdate": {
917 "oldRev": "90f173846e3af9154517b88543ffbd1691f31366",
918 "newRev": "d479a0bfcb34da57a31adb2a595c0cf687812543",
919 "refName": "master",
920 "project": "org/project",
921 }
922 }
James E. Blairdaabed22012-08-15 15:38:57 -0700923 self.fake_gerrit.addEvent(e)
924 self.waitUntilSettled()
925
Monty Taylor6bef8ef2013-06-02 08:17:12 -0400926 job_names = [x.name for x in self.history]
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400927 self.assertEqual(len(self.history), 1)
928 self.assertIn('project-post', job_names)
James E. Blairc6294a52012-08-17 10:19:48 -0700929
K Jonathan Harkerf95e7232015-04-29 13:33:16 -0700930 def test_post_ignore_deletes(self):
931 "Test that deleting refs does not trigger post jobs"
932
933 e = {
934 "type": "ref-updated",
935 "submitter": {
936 "name": "User Name",
937 },
938 "refUpdate": {
939 "oldRev": "90f173846e3af9154517b88543ffbd1691f31366",
940 "newRev": "0000000000000000000000000000000000000000",
941 "refName": "master",
942 "project": "org/project",
943 }
944 }
945 self.fake_gerrit.addEvent(e)
946 self.waitUntilSettled()
947
948 job_names = [x.name for x in self.history]
949 self.assertEqual(len(self.history), 0)
950 self.assertNotIn('project-post', job_names)
951
952 def test_post_ignore_deletes_negative(self):
953 "Test that deleting refs does trigger post jobs"
954
955 self.config.set('zuul', 'layout_config',
956 'tests/fixtures/layout-dont-ignore-deletes.yaml')
957 self.sched.reconfigure(self.config)
958
959 e = {
960 "type": "ref-updated",
961 "submitter": {
962 "name": "User Name",
963 },
964 "refUpdate": {
965 "oldRev": "90f173846e3af9154517b88543ffbd1691f31366",
966 "newRev": "0000000000000000000000000000000000000000",
967 "refName": "master",
968 "project": "org/project",
969 }
970 }
971 self.fake_gerrit.addEvent(e)
972 self.waitUntilSettled()
973
974 job_names = [x.name for x in self.history]
975 self.assertEqual(len(self.history), 1)
976 self.assertIn('project-post', job_names)
977
James E. Blairc6294a52012-08-17 10:19:48 -0700978 def test_build_configuration_branch(self):
979 "Test that the right commits are on alternate branches"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700980
981 self.gearman_server.hold_jobs_in_queue = True
James E. Blairc6294a52012-08-17 10:19:48 -0700982 A = self.fake_gerrit.addFakeChange('org/project', 'mp', 'A')
983 B = self.fake_gerrit.addFakeChange('org/project', 'mp', 'B')
984 C = self.fake_gerrit.addFakeChange('org/project', 'mp', 'C')
985 A.addApproval('CRVW', 2)
986 B.addApproval('CRVW', 2)
987 C.addApproval('CRVW', 2)
988 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
989 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
990 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
991 self.waitUntilSettled()
992
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700993 self.gearman_server.release('.*-merge')
James E. Blairc6294a52012-08-17 10:19:48 -0700994 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700995 self.gearman_server.release('.*-merge')
James E. Blairc6294a52012-08-17 10:19:48 -0700996 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700997 self.gearman_server.release('.*-merge')
James E. Blairc6294a52012-08-17 10:19:48 -0700998 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -0700999 queue = self.gearman_server.getQueue()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001000 ref = self.getParameter(queue[-1], 'ZUUL_REF')
1001 self.gearman_server.hold_jobs_in_queue = False
1002 self.gearman_server.release()
James E. Blairc6294a52012-08-17 10:19:48 -07001003 self.waitUntilSettled()
1004
Monty Taylorbc758832013-06-17 17:22:42 -04001005 path = os.path.join(self.git_root, "org/project")
James E. Blairc6294a52012-08-17 10:19:48 -07001006 repo = git.Repo(path)
1007 repo_messages = [c.message.strip() for c in repo.iter_commits(ref)]
1008 repo_messages.reverse()
James E. Blairc6294a52012-08-17 10:19:48 -07001009 correct_messages = ['initial commit', 'mp commit', 'A-1', 'B-1', 'C-1']
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001010 self.assertEqual(repo_messages, correct_messages)
James E. Blairc6294a52012-08-17 10:19:48 -07001011
1012 def test_build_configuration_branch_interaction(self):
1013 "Test that switching between branches works"
1014 self.test_build_configuration()
1015 self.test_build_configuration_branch()
1016 # C has been merged, undo that
Monty Taylorbc758832013-06-17 17:22:42 -04001017 path = os.path.join(self.upstream_root, "org/project")
James E. Blairc6294a52012-08-17 10:19:48 -07001018 repo = git.Repo(path)
1019 repo.heads.master.commit = repo.commit('init')
1020 self.test_build_configuration()
1021
1022 def test_build_configuration_multi_branch(self):
1023 "Test that dependent changes on multiple branches are merged"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001024
1025 self.gearman_server.hold_jobs_in_queue = True
James E. Blairc6294a52012-08-17 10:19:48 -07001026 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1027 B = self.fake_gerrit.addFakeChange('org/project', 'mp', 'B')
1028 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1029 A.addApproval('CRVW', 2)
1030 B.addApproval('CRVW', 2)
1031 C.addApproval('CRVW', 2)
1032 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1033 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1034 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1035 self.waitUntilSettled()
James E. Blairbb1fe502014-03-04 10:15:06 -08001036 queue = self.gearman_server.getQueue()
1037 job_A = None
1038 for job in queue:
1039 if 'project-merge' in job.name:
1040 job_A = job
1041 ref_A = self.getParameter(job_A, 'ZUUL_REF')
1042 commit_A = self.getParameter(job_A, 'ZUUL_COMMIT')
1043 self.log.debug("Got Zuul ref for change A: %s" % ref_A)
1044 self.log.debug("Got Zuul commit for change A: %s" % commit_A)
James E. Blairc6294a52012-08-17 10:19:48 -07001045
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001046 self.gearman_server.release('.*-merge')
James E. Blairc6294a52012-08-17 10:19:48 -07001047 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -07001048 queue = self.gearman_server.getQueue()
James E. Blaird320d7e2013-07-30 16:36:20 -07001049 job_B = None
1050 for job in queue:
1051 if 'project-merge' in job.name:
1052 job_B = job
1053 ref_B = self.getParameter(job_B, 'ZUUL_REF')
James E. Blairbb1fe502014-03-04 10:15:06 -08001054 commit_B = self.getParameter(job_B, 'ZUUL_COMMIT')
James E. Blairf750aa02013-07-15 14:11:24 -07001055 self.log.debug("Got Zuul ref for change B: %s" % ref_B)
James E. Blairbb1fe502014-03-04 10:15:06 -08001056 self.log.debug("Got Zuul commit for change B: %s" % commit_B)
1057
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001058 self.gearman_server.release('.*-merge')
James E. Blairc6294a52012-08-17 10:19:48 -07001059 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -07001060 queue = self.gearman_server.getQueue()
James E. Blaird320d7e2013-07-30 16:36:20 -07001061 for job in queue:
1062 if 'project-merge' in job.name:
1063 job_C = job
1064 ref_C = self.getParameter(job_C, 'ZUUL_REF')
James E. Blairbb1fe502014-03-04 10:15:06 -08001065 commit_C = self.getParameter(job_C, 'ZUUL_COMMIT')
James E. Blairf750aa02013-07-15 14:11:24 -07001066 self.log.debug("Got Zuul ref for change C: %s" % ref_C)
James E. Blairbb1fe502014-03-04 10:15:06 -08001067 self.log.debug("Got Zuul commit for change C: %s" % commit_C)
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001068 self.gearman_server.hold_jobs_in_queue = False
1069 self.gearman_server.release()
James E. Blairc6294a52012-08-17 10:19:48 -07001070 self.waitUntilSettled()
1071
Monty Taylorbc758832013-06-17 17:22:42 -04001072 path = os.path.join(self.git_root, "org/project")
James E. Blairc6294a52012-08-17 10:19:48 -07001073 repo = git.Repo(path)
1074
1075 repo_messages = [c.message.strip()
James E. Blairf750aa02013-07-15 14:11:24 -07001076 for c in repo.iter_commits(ref_C)]
James E. Blairbb1fe502014-03-04 10:15:06 -08001077 repo_shas = [c.hexsha for c in repo.iter_commits(ref_C)]
James E. Blairc6294a52012-08-17 10:19:48 -07001078 repo_messages.reverse()
James E. Blairc6294a52012-08-17 10:19:48 -07001079 correct_messages = ['initial commit', 'A-1', 'C-1']
James E. Blairbb1fe502014-03-04 10:15:06 -08001080 # Ensure the right commits are in the history for this ref
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001081 self.assertEqual(repo_messages, correct_messages)
James E. Blairbb1fe502014-03-04 10:15:06 -08001082 # Ensure ZUUL_REF -> ZUUL_COMMIT
1083 self.assertEqual(repo_shas[0], commit_C)
James E. Blairc6294a52012-08-17 10:19:48 -07001084
1085 repo_messages = [c.message.strip()
James E. Blairf750aa02013-07-15 14:11:24 -07001086 for c in repo.iter_commits(ref_B)]
James E. Blairbb1fe502014-03-04 10:15:06 -08001087 repo_shas = [c.hexsha for c in repo.iter_commits(ref_B)]
James E. Blairc6294a52012-08-17 10:19:48 -07001088 repo_messages.reverse()
James E. Blairc6294a52012-08-17 10:19:48 -07001089 correct_messages = ['initial commit', 'mp commit', 'B-1']
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001090 self.assertEqual(repo_messages, correct_messages)
James E. Blairbb1fe502014-03-04 10:15:06 -08001091 self.assertEqual(repo_shas[0], commit_B)
1092
1093 repo_messages = [c.message.strip()
1094 for c in repo.iter_commits(ref_A)]
1095 repo_shas = [c.hexsha for c in repo.iter_commits(ref_A)]
1096 repo_messages.reverse()
1097 correct_messages = ['initial commit', 'A-1']
1098 self.assertEqual(repo_messages, correct_messages)
1099 self.assertEqual(repo_shas[0], commit_A)
1100
1101 self.assertNotEqual(ref_A, ref_B, ref_C)
1102 self.assertNotEqual(commit_A, commit_B, commit_C)
James E. Blair7f71c802012-08-22 13:04:32 -07001103
1104 def test_one_job_project(self):
1105 "Test that queueing works with one job"
1106 A = self.fake_gerrit.addFakeChange('org/one-job-project',
1107 'master', 'A')
1108 B = self.fake_gerrit.addFakeChange('org/one-job-project',
1109 'master', 'B')
1110 A.addApproval('CRVW', 2)
1111 B.addApproval('CRVW', 2)
1112 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1113 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1114 self.waitUntilSettled()
1115
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001116 self.assertEqual(A.data['status'], 'MERGED')
1117 self.assertEqual(A.reported, 2)
1118 self.assertEqual(B.data['status'], 'MERGED')
1119 self.assertEqual(B.reported, 2)
James E. Blaircaec0c52012-08-22 14:52:22 -07001120
Antoine Musso80edd5a2013-02-13 15:37:53 +01001121 def test_job_from_templates_launched(self):
1122 "Test whether a job generated via a template can be launched"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001123
Antoine Musso80edd5a2013-02-13 15:37:53 +01001124 A = self.fake_gerrit.addFakeChange(
1125 'org/templated-project', 'master', 'A')
1126 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1127 self.waitUntilSettled()
Antoine Musso80edd5a2013-02-13 15:37:53 +01001128
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001129 self.assertEqual(self.getJobFromHistory('project-test1').result,
1130 'SUCCESS')
1131 self.assertEqual(self.getJobFromHistory('project-test2').result,
1132 'SUCCESS')
Antoine Musso80edd5a2013-02-13 15:37:53 +01001133
James E. Blair3e98c022013-12-16 15:25:38 -08001134 def test_layered_templates(self):
1135 "Test whether a job generated via a template can be launched"
1136
1137 A = self.fake_gerrit.addFakeChange(
1138 'org/layered-project', 'master', 'A')
1139 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1140 self.waitUntilSettled()
1141
1142 self.assertEqual(self.getJobFromHistory('project-test1').result,
1143 'SUCCESS')
1144 self.assertEqual(self.getJobFromHistory('project-test2').result,
1145 'SUCCESS')
James E. Blairaea6cf62013-12-16 15:38:12 -08001146 self.assertEqual(self.getJobFromHistory('layered-project-test3'
1147 ).result, 'SUCCESS')
1148 self.assertEqual(self.getJobFromHistory('layered-project-test4'
1149 ).result, 'SUCCESS')
James E. Blair12a92b12014-03-26 11:54:53 -07001150 self.assertEqual(self.getJobFromHistory('layered-project-foo-test5'
1151 ).result, 'SUCCESS')
James E. Blair3e98c022013-12-16 15:25:38 -08001152 self.assertEqual(self.getJobFromHistory('project-test6').result,
1153 'SUCCESS')
1154
James E. Blaircaec0c52012-08-22 14:52:22 -07001155 def test_dependent_changes_dequeue(self):
1156 "Test that dependent patches are not needlessly tested"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001157
James E. Blaircaec0c52012-08-22 14:52:22 -07001158 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1159 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1160 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1161 A.addApproval('CRVW', 2)
1162 B.addApproval('CRVW', 2)
1163 C.addApproval('CRVW', 2)
1164
1165 M1 = self.fake_gerrit.addFakeChange('org/project', 'master', 'M1')
1166 M1.setMerged()
1167
1168 # C -> B -> A -> M1
1169
1170 C.setDependsOn(B, 1)
1171 B.setDependsOn(A, 1)
1172 A.setDependsOn(M1, 1)
1173
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001174 self.worker.addFailTest('project-merge', A)
James E. Blaircaec0c52012-08-22 14:52:22 -07001175
1176 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1177 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1178 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1179
1180 self.waitUntilSettled()
1181
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001182 self.assertEqual(A.data['status'], 'NEW')
1183 self.assertEqual(A.reported, 2)
1184 self.assertEqual(B.data['status'], 'NEW')
1185 self.assertEqual(B.reported, 2)
1186 self.assertEqual(C.data['status'], 'NEW')
1187 self.assertEqual(C.reported, 2)
1188 self.assertEqual(len(self.history), 1)
James E. Blairec590122012-08-22 15:19:31 -07001189
James E. Blair972e3c72013-08-29 12:04:55 -07001190 def test_failing_dependent_changes(self):
1191 "Test that failing dependent patches are taken out of stream"
1192 self.worker.hold_jobs_in_build = True
1193 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1194 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1195 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1196 D = self.fake_gerrit.addFakeChange('org/project', 'master', 'D')
1197 E = self.fake_gerrit.addFakeChange('org/project', 'master', 'E')
1198 A.addApproval('CRVW', 2)
1199 B.addApproval('CRVW', 2)
1200 C.addApproval('CRVW', 2)
1201 D.addApproval('CRVW', 2)
1202 E.addApproval('CRVW', 2)
1203
1204 # E, D -> C -> B, A
1205
1206 D.setDependsOn(C, 1)
1207 C.setDependsOn(B, 1)
1208
1209 self.worker.addFailTest('project-test1', B)
1210
1211 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1212 self.fake_gerrit.addEvent(D.addApproval('APRV', 1))
1213 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1214 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1215 self.fake_gerrit.addEvent(E.addApproval('APRV', 1))
1216
1217 self.waitUntilSettled()
1218 self.worker.release('.*-merge')
1219 self.waitUntilSettled()
1220 self.worker.release('.*-merge')
1221 self.waitUntilSettled()
1222 self.worker.release('.*-merge')
1223 self.waitUntilSettled()
1224 self.worker.release('.*-merge')
1225 self.waitUntilSettled()
1226 self.worker.release('.*-merge')
1227 self.waitUntilSettled()
1228
1229 self.worker.hold_jobs_in_build = False
1230 for build in self.builds:
1231 if build.parameters['ZUUL_CHANGE'] != '1':
1232 build.release()
1233 self.waitUntilSettled()
1234
1235 self.worker.release()
1236 self.waitUntilSettled()
1237
1238 self.assertEqual(A.data['status'], 'MERGED')
1239 self.assertEqual(A.reported, 2)
Jeremy Stanley10837132014-08-02 16:10:56 +00001240 self.assertIn('Build succeeded', A.messages[1])
James E. Blair972e3c72013-08-29 12:04:55 -07001241 self.assertEqual(B.data['status'], 'NEW')
1242 self.assertEqual(B.reported, 2)
Jeremy Stanley10837132014-08-02 16:10:56 +00001243 self.assertIn('Build failed', B.messages[1])
James E. Blair972e3c72013-08-29 12:04:55 -07001244 self.assertEqual(C.data['status'], 'NEW')
1245 self.assertEqual(C.reported, 2)
Jeremy Stanley10837132014-08-02 16:10:56 +00001246 self.assertIn('depends on a change', C.messages[1])
James E. Blair972e3c72013-08-29 12:04:55 -07001247 self.assertEqual(D.data['status'], 'NEW')
1248 self.assertEqual(D.reported, 2)
Jeremy Stanley10837132014-08-02 16:10:56 +00001249 self.assertIn('depends on a change', D.messages[1])
James E. Blair972e3c72013-08-29 12:04:55 -07001250 self.assertEqual(E.data['status'], 'MERGED')
1251 self.assertEqual(E.reported, 2)
Jeremy Stanley10837132014-08-02 16:10:56 +00001252 self.assertIn('Build succeeded', E.messages[1])
James E. Blair972e3c72013-08-29 12:04:55 -07001253 self.assertEqual(len(self.history), 18)
1254
James E. Blairec590122012-08-22 15:19:31 -07001255 def test_head_is_dequeued_once(self):
James E. Blair2fa50962013-01-30 21:50:41 -08001256 "Test that if a change at the head fails it is dequeued only once"
James E. Blairec590122012-08-22 15:19:31 -07001257 # If it's dequeued more than once, we should see extra
1258 # aborted jobs.
James E. Blairec590122012-08-22 15:19:31 -07001259
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001260 self.worker.hold_jobs_in_build = True
James E. Blairec590122012-08-22 15:19:31 -07001261 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
1262 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
1263 C = self.fake_gerrit.addFakeChange('org/project1', 'master', 'C')
1264 A.addApproval('CRVW', 2)
1265 B.addApproval('CRVW', 2)
1266 C.addApproval('CRVW', 2)
1267
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001268 self.worker.addFailTest('project1-test1', A)
1269 self.worker.addFailTest('project1-test2', A)
1270 self.worker.addFailTest('project1-project2-integration', A)
James E. Blairec590122012-08-22 15:19:31 -07001271
1272 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1273 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1274 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1275
1276 self.waitUntilSettled()
James E. Blairec590122012-08-22 15:19:31 -07001277
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001278 self.assertEqual(len(self.builds), 1)
1279 self.assertEqual(self.builds[0].name, 'project1-merge')
1280 self.assertTrue(self.job_has_changes(self.builds[0], A))
James E. Blairec590122012-08-22 15:19:31 -07001281
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001282 self.worker.release('.*-merge')
James E. Blairec590122012-08-22 15:19:31 -07001283 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001284 self.worker.release('.*-merge')
James E. Blairec590122012-08-22 15:19:31 -07001285 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001286 self.worker.release('.*-merge')
James E. Blairec590122012-08-22 15:19:31 -07001287 self.waitUntilSettled()
1288
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001289 self.assertEqual(len(self.builds), 9)
1290 self.assertEqual(self.builds[0].name, 'project1-test1')
1291 self.assertEqual(self.builds[1].name, 'project1-test2')
1292 self.assertEqual(self.builds[2].name, 'project1-project2-integration')
1293 self.assertEqual(self.builds[3].name, 'project1-test1')
1294 self.assertEqual(self.builds[4].name, 'project1-test2')
1295 self.assertEqual(self.builds[5].name, 'project1-project2-integration')
1296 self.assertEqual(self.builds[6].name, 'project1-test1')
1297 self.assertEqual(self.builds[7].name, 'project1-test2')
1298 self.assertEqual(self.builds[8].name, 'project1-project2-integration')
James E. Blairec590122012-08-22 15:19:31 -07001299
Monty Taylor6bef8ef2013-06-02 08:17:12 -04001300 self.release(self.builds[0])
James E. Blairec590122012-08-22 15:19:31 -07001301 self.waitUntilSettled()
1302
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001303 self.assertEqual(len(self.builds), 3) # test2,integration, merge for B
1304 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 6)
James E. Blairec590122012-08-22 15:19:31 -07001305
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001306 self.worker.hold_jobs_in_build = False
1307 self.worker.release()
James E. Blairec590122012-08-22 15:19:31 -07001308 self.waitUntilSettled()
1309
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001310 self.assertEqual(len(self.builds), 0)
1311 self.assertEqual(len(self.history), 20)
James E. Blaircaec0c52012-08-22 14:52:22 -07001312
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001313 self.assertEqual(A.data['status'], 'NEW')
1314 self.assertEqual(B.data['status'], 'MERGED')
1315 self.assertEqual(C.data['status'], 'MERGED')
1316 self.assertEqual(A.reported, 2)
1317 self.assertEqual(B.reported, 2)
1318 self.assertEqual(C.reported, 2)
James E. Blair4ec821f2012-08-23 15:28:28 -07001319
1320 def test_nonvoting_job(self):
1321 "Test that non-voting jobs don't vote."
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001322
James E. Blair4ec821f2012-08-23 15:28:28 -07001323 A = self.fake_gerrit.addFakeChange('org/nonvoting-project',
1324 'master', 'A')
1325 A.addApproval('CRVW', 2)
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001326 self.worker.addFailTest('nonvoting-project-test2', A)
James E. Blair4ec821f2012-08-23 15:28:28 -07001327 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1328
1329 self.waitUntilSettled()
James E. Blair4ec821f2012-08-23 15:28:28 -07001330
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001331 self.assertEqual(A.data['status'], 'MERGED')
1332 self.assertEqual(A.reported, 2)
1333 self.assertEqual(
1334 self.getJobFromHistory('nonvoting-project-merge').result,
1335 'SUCCESS')
1336 self.assertEqual(
1337 self.getJobFromHistory('nonvoting-project-test1').result,
1338 'SUCCESS')
1339 self.assertEqual(
1340 self.getJobFromHistory('nonvoting-project-test2').result,
1341 'FAILURE')
James E. Blaire0487072012-08-29 17:38:31 -07001342
James E. Blair5821bd92015-09-16 08:48:15 -07001343 for build in self.builds:
1344 self.assertEqual(build.parameters['ZUUL_VOTING'], '0')
1345
James E. Blaire0487072012-08-29 17:38:31 -07001346 def test_check_queue_success(self):
1347 "Test successful check queue jobs."
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001348
James E. Blaire0487072012-08-29 17:38:31 -07001349 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1350 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1351
1352 self.waitUntilSettled()
James E. Blaire0487072012-08-29 17:38:31 -07001353
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001354 self.assertEqual(A.data['status'], 'NEW')
1355 self.assertEqual(A.reported, 1)
1356 self.assertEqual(self.getJobFromHistory('project-merge').result,
1357 'SUCCESS')
1358 self.assertEqual(self.getJobFromHistory('project-test1').result,
1359 'SUCCESS')
1360 self.assertEqual(self.getJobFromHistory('project-test2').result,
1361 'SUCCESS')
James E. Blaire0487072012-08-29 17:38:31 -07001362
1363 def test_check_queue_failure(self):
1364 "Test failed check queue jobs."
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001365
James E. Blaire0487072012-08-29 17:38:31 -07001366 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001367 self.worker.addFailTest('project-test2', A)
James E. Blaire0487072012-08-29 17:38:31 -07001368 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1369
1370 self.waitUntilSettled()
James E. Blaire0487072012-08-29 17:38:31 -07001371
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001372 self.assertEqual(A.data['status'], 'NEW')
1373 self.assertEqual(A.reported, 1)
1374 self.assertEqual(self.getJobFromHistory('project-merge').result,
James E. Blair78e31b32013-07-09 09:11:34 -07001375 'SUCCESS')
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001376 self.assertEqual(self.getJobFromHistory('project-test1').result,
1377 'SUCCESS')
1378 self.assertEqual(self.getJobFromHistory('project-test2').result,
1379 'FAILURE')
James E. Blair127bc182012-08-28 15:55:15 -07001380
1381 def test_dependent_behind_dequeue(self):
1382 "test that dependent changes behind dequeued changes work"
1383 # This complicated test is a reproduction of a real life bug
1384 self.sched.reconfigure(self.config)
James E. Blair127bc182012-08-28 15:55:15 -07001385
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001386 self.worker.hold_jobs_in_build = True
James E. Blair127bc182012-08-28 15:55:15 -07001387 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
1388 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
1389 C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
1390 D = self.fake_gerrit.addFakeChange('org/project2', 'master', 'D')
1391 E = self.fake_gerrit.addFakeChange('org/project2', 'master', 'E')
1392 F = self.fake_gerrit.addFakeChange('org/project3', 'master', 'F')
1393 D.setDependsOn(C, 1)
1394 E.setDependsOn(D, 1)
1395 A.addApproval('CRVW', 2)
1396 B.addApproval('CRVW', 2)
1397 C.addApproval('CRVW', 2)
1398 D.addApproval('CRVW', 2)
1399 E.addApproval('CRVW', 2)
1400 F.addApproval('CRVW', 2)
1401
1402 A.fail_merge = True
James E. Blair127bc182012-08-28 15:55:15 -07001403
1404 # Change object re-use in the gerrit trigger is hidden if
1405 # changes are added in quick succession; waiting makes it more
1406 # like real life.
1407 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1408 self.waitUntilSettled()
1409 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1410 self.waitUntilSettled()
1411
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001412 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001413 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001414 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001415 self.waitUntilSettled()
1416
1417 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1418 self.waitUntilSettled()
1419 self.fake_gerrit.addEvent(D.addApproval('APRV', 1))
1420 self.waitUntilSettled()
1421 self.fake_gerrit.addEvent(E.addApproval('APRV', 1))
1422 self.waitUntilSettled()
1423 self.fake_gerrit.addEvent(F.addApproval('APRV', 1))
1424 self.waitUntilSettled()
1425
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001426 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001427 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001428 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001429 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001430 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001431 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001432 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001433 self.waitUntilSettled()
1434
1435 # all jobs running
James E. Blaire955e062012-10-08 09:49:03 -07001436
1437 # Grab pointers to the jobs we want to release before
1438 # releasing any, because list indexes may change as
1439 # the jobs complete.
Monty Taylor6bef8ef2013-06-02 08:17:12 -04001440 a, b, c = self.builds[:3]
James E. Blaire955e062012-10-08 09:49:03 -07001441 a.release()
1442 b.release()
1443 c.release()
James E. Blair127bc182012-08-28 15:55:15 -07001444 self.waitUntilSettled()
1445
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001446 self.worker.hold_jobs_in_build = False
1447 self.worker.release()
James E. Blair127bc182012-08-28 15:55:15 -07001448 self.waitUntilSettled()
1449
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001450 self.assertEqual(A.data['status'], 'NEW')
1451 self.assertEqual(B.data['status'], 'MERGED')
1452 self.assertEqual(C.data['status'], 'MERGED')
1453 self.assertEqual(D.data['status'], 'MERGED')
1454 self.assertEqual(E.data['status'], 'MERGED')
1455 self.assertEqual(F.data['status'], 'MERGED')
James E. Blair127bc182012-08-28 15:55:15 -07001456
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001457 self.assertEqual(A.reported, 2)
1458 self.assertEqual(B.reported, 2)
1459 self.assertEqual(C.reported, 2)
1460 self.assertEqual(D.reported, 2)
1461 self.assertEqual(E.reported, 2)
1462 self.assertEqual(F.reported, 2)
James E. Blair127bc182012-08-28 15:55:15 -07001463
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001464 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 15)
1465 self.assertEqual(len(self.history), 44)
James E. Blair05fed602012-09-07 12:45:24 -07001466
1467 def test_merger_repack(self):
1468 "Test that the merger works after a repack"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001469
James E. Blair05fed602012-09-07 12:45:24 -07001470 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1471 A.addApproval('CRVW', 2)
1472 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1473 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001474 self.assertEqual(self.getJobFromHistory('project-merge').result,
1475 'SUCCESS')
1476 self.assertEqual(self.getJobFromHistory('project-test1').result,
1477 'SUCCESS')
1478 self.assertEqual(self.getJobFromHistory('project-test2').result,
1479 'SUCCESS')
1480 self.assertEqual(A.data['status'], 'MERGED')
1481 self.assertEqual(A.reported, 2)
James E. Blair05fed602012-09-07 12:45:24 -07001482 self.assertEmptyQueues()
James E. Blair4ca985f2013-05-30 12:27:43 -07001483 self.worker.build_history = []
James E. Blair05fed602012-09-07 12:45:24 -07001484
Monty Taylorbc758832013-06-17 17:22:42 -04001485 path = os.path.join(self.git_root, "org/project")
Morgan Fainberg4c6a7742016-05-27 08:42:17 -07001486 print(repack_repo(path))
James E. Blair05fed602012-09-07 12:45:24 -07001487
1488 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1489 A.addApproval('CRVW', 2)
1490 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1491 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001492 self.assertEqual(self.getJobFromHistory('project-merge').result,
1493 'SUCCESS')
1494 self.assertEqual(self.getJobFromHistory('project-test1').result,
1495 'SUCCESS')
1496 self.assertEqual(self.getJobFromHistory('project-test2').result,
1497 'SUCCESS')
1498 self.assertEqual(A.data['status'], 'MERGED')
1499 self.assertEqual(A.reported, 2)
James E. Blair7ee88a22012-09-12 18:59:31 +02001500
James E. Blair4886f282012-11-15 09:27:33 -08001501 def test_merger_repack_large_change(self):
1502 "Test that the merger works with large changes after a repack"
1503 # https://bugs.launchpad.net/zuul/+bug/1078946
James E. Blairac2c3242014-01-24 13:38:51 -08001504 # This test assumes the repo is already cloned; make sure it is
Joshua Hesketh352264b2015-08-11 23:42:08 +10001505 url = self.fake_gerrit.getGitUrl(
James E. Blairac2c3242014-01-24 13:38:51 -08001506 self.sched.layout.projects['org/project1'])
James E. Blair4076e2b2014-01-28 12:42:20 -08001507 self.merge_server.merger.addProject('org/project1', url)
James E. Blair4886f282012-11-15 09:27:33 -08001508 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
1509 A.addPatchset(large=True)
Monty Taylorbc758832013-06-17 17:22:42 -04001510 path = os.path.join(self.upstream_root, "org/project1")
Morgan Fainberg4c6a7742016-05-27 08:42:17 -07001511 print(repack_repo(path))
Monty Taylorbc758832013-06-17 17:22:42 -04001512 path = os.path.join(self.git_root, "org/project1")
Morgan Fainberg4c6a7742016-05-27 08:42:17 -07001513 print(repack_repo(path))
James E. Blair4886f282012-11-15 09:27:33 -08001514
1515 A.addApproval('CRVW', 2)
1516 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1517 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001518 self.assertEqual(self.getJobFromHistory('project1-merge').result,
1519 'SUCCESS')
1520 self.assertEqual(self.getJobFromHistory('project1-test1').result,
1521 'SUCCESS')
1522 self.assertEqual(self.getJobFromHistory('project1-test2').result,
1523 'SUCCESS')
1524 self.assertEqual(A.data['status'], 'MERGED')
1525 self.assertEqual(A.reported, 2)
James E. Blair4886f282012-11-15 09:27:33 -08001526
James E. Blair7ee88a22012-09-12 18:59:31 +02001527 def test_nonexistent_job(self):
1528 "Test launching a job that doesn't exist"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001529 # Set to the state immediately after a restart
1530 self.resetGearmanServer()
1531 self.launcher.negative_function_cache_ttl = 0
James E. Blair7ee88a22012-09-12 18:59:31 +02001532
1533 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1534 A.addApproval('CRVW', 2)
1535 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1536 # There may be a thread about to report a lost change
1537 while A.reported < 2:
1538 self.waitUntilSettled()
Monty Taylor6bef8ef2013-06-02 08:17:12 -04001539 job_names = [x.name for x in self.history]
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001540 self.assertFalse(job_names)
1541 self.assertEqual(A.data['status'], 'NEW')
1542 self.assertEqual(A.reported, 2)
James E. Blair7ee88a22012-09-12 18:59:31 +02001543 self.assertEmptyQueues()
1544
1545 # Make sure things still work:
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001546 self.registerJobs()
James E. Blair7ee88a22012-09-12 18:59:31 +02001547 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1548 A.addApproval('CRVW', 2)
1549 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1550 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001551 self.assertEqual(self.getJobFromHistory('project-merge').result,
1552 'SUCCESS')
1553 self.assertEqual(self.getJobFromHistory('project-test1').result,
1554 'SUCCESS')
1555 self.assertEqual(self.getJobFromHistory('project-test2').result,
1556 'SUCCESS')
1557 self.assertEqual(A.data['status'], 'MERGED')
1558 self.assertEqual(A.reported, 2)
James E. Blairf62d4282012-12-31 17:01:50 -08001559
1560 def test_single_nonexistent_post_job(self):
1561 "Test launching a single post job that doesn't exist"
James E. Blairf62d4282012-12-31 17:01:50 -08001562 e = {
1563 "type": "ref-updated",
1564 "submitter": {
1565 "name": "User Name",
1566 },
1567 "refUpdate": {
1568 "oldRev": "90f173846e3af9154517b88543ffbd1691f31366",
1569 "newRev": "d479a0bfcb34da57a31adb2a595c0cf687812543",
1570 "refName": "master",
1571 "project": "org/project",
1572 }
1573 }
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001574 # Set to the state immediately after a restart
1575 self.resetGearmanServer()
1576 self.launcher.negative_function_cache_ttl = 0
1577
James E. Blairf62d4282012-12-31 17:01:50 -08001578 self.fake_gerrit.addEvent(e)
1579 self.waitUntilSettled()
1580
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001581 self.assertEqual(len(self.history), 0)
James E. Blair2fa50962013-01-30 21:50:41 -08001582
1583 def test_new_patchset_dequeues_old(self):
1584 "Test that a new patchset causes the old to be dequeued"
1585 # D -> C (depends on B) -> B (depends on A) -> A -> M
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001586 self.worker.hold_jobs_in_build = True
James E. Blair2fa50962013-01-30 21:50:41 -08001587 M = self.fake_gerrit.addFakeChange('org/project', 'master', 'M')
1588 M.setMerged()
1589
1590 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1591 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1592 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1593 D = self.fake_gerrit.addFakeChange('org/project', 'master', 'D')
1594 A.addApproval('CRVW', 2)
1595 B.addApproval('CRVW', 2)
1596 C.addApproval('CRVW', 2)
1597 D.addApproval('CRVW', 2)
1598
1599 C.setDependsOn(B, 1)
1600 B.setDependsOn(A, 1)
1601 A.setDependsOn(M, 1)
1602
1603 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1604 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1605 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1606 self.fake_gerrit.addEvent(D.addApproval('APRV', 1))
1607 self.waitUntilSettled()
1608
1609 B.addPatchset()
1610 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(2))
1611 self.waitUntilSettled()
1612
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001613 self.worker.hold_jobs_in_build = False
1614 self.worker.release()
James E. Blair2fa50962013-01-30 21:50:41 -08001615 self.waitUntilSettled()
1616
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001617 self.assertEqual(A.data['status'], 'MERGED')
1618 self.assertEqual(A.reported, 2)
1619 self.assertEqual(B.data['status'], 'NEW')
1620 self.assertEqual(B.reported, 2)
1621 self.assertEqual(C.data['status'], 'NEW')
1622 self.assertEqual(C.reported, 2)
1623 self.assertEqual(D.data['status'], 'MERGED')
1624 self.assertEqual(D.reported, 2)
1625 self.assertEqual(len(self.history), 9) # 3 each for A, B, D.
James E. Blair2fa50962013-01-30 21:50:41 -08001626
James E. Blairba437362015-02-07 11:41:52 -08001627 def test_new_patchset_check(self):
1628 "Test a new patchset in check"
Antoine Mussobd86a312014-01-08 14:51:33 +01001629
1630 self.worker.hold_jobs_in_build = True
1631
1632 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
James E. Blairba437362015-02-07 11:41:52 -08001633 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1634 check_pipeline = self.sched.layout.pipelines['check']
1635
1636 # Add two git-dependent changes
1637 B.setDependsOn(A, 1)
1638 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1639 self.waitUntilSettled()
Antoine Mussobd86a312014-01-08 14:51:33 +01001640 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1641 self.waitUntilSettled()
James E. Blairba437362015-02-07 11:41:52 -08001642
1643 # A live item, and a non-live/live pair
1644 items = check_pipeline.getAllItems()
1645 self.assertEqual(len(items), 3)
1646
1647 self.assertEqual(items[0].change.number, '1')
1648 self.assertEqual(items[0].change.patchset, '1')
1649 self.assertFalse(items[0].live)
1650
1651 self.assertEqual(items[1].change.number, '2')
1652 self.assertEqual(items[1].change.patchset, '1')
1653 self.assertTrue(items[1].live)
1654
1655 self.assertEqual(items[2].change.number, '1')
1656 self.assertEqual(items[2].change.patchset, '1')
1657 self.assertTrue(items[2].live)
1658
1659 # Add a new patchset to A
1660 A.addPatchset()
1661 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
1662 self.waitUntilSettled()
1663
1664 # The live copy of A,1 should be gone, but the non-live and B
1665 # should continue, and we should have a new A,2
1666 items = check_pipeline.getAllItems()
1667 self.assertEqual(len(items), 3)
1668
1669 self.assertEqual(items[0].change.number, '1')
1670 self.assertEqual(items[0].change.patchset, '1')
1671 self.assertFalse(items[0].live)
1672
1673 self.assertEqual(items[1].change.number, '2')
1674 self.assertEqual(items[1].change.patchset, '1')
1675 self.assertTrue(items[1].live)
1676
1677 self.assertEqual(items[2].change.number, '1')
1678 self.assertEqual(items[2].change.patchset, '2')
1679 self.assertTrue(items[2].live)
1680
1681 # Add a new patchset to B
1682 B.addPatchset()
1683 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(2))
1684 self.waitUntilSettled()
1685
1686 # The live copy of B,1 should be gone, and it's non-live copy of A,1
1687 # but we should have a new B,2 (still based on A,1)
1688 items = check_pipeline.getAllItems()
1689 self.assertEqual(len(items), 3)
1690
1691 self.assertEqual(items[0].change.number, '1')
1692 self.assertEqual(items[0].change.patchset, '2')
1693 self.assertTrue(items[0].live)
1694
1695 self.assertEqual(items[1].change.number, '1')
1696 self.assertEqual(items[1].change.patchset, '1')
1697 self.assertFalse(items[1].live)
1698
1699 self.assertEqual(items[2].change.number, '2')
1700 self.assertEqual(items[2].change.patchset, '2')
1701 self.assertTrue(items[2].live)
1702
1703 self.builds[0].release()
1704 self.waitUntilSettled()
1705 self.builds[0].release()
1706 self.waitUntilSettled()
1707 self.worker.hold_jobs_in_build = False
1708 self.worker.release()
1709 self.waitUntilSettled()
1710
1711 self.assertEqual(A.reported, 1)
1712 self.assertEqual(B.reported, 1)
1713 self.assertEqual(self.history[0].result, 'ABORTED')
1714 self.assertEqual(self.history[0].changes, '1,1')
1715 self.assertEqual(self.history[1].result, 'ABORTED')
1716 self.assertEqual(self.history[1].changes, '1,1 2,1')
1717 self.assertEqual(self.history[2].result, 'SUCCESS')
1718 self.assertEqual(self.history[2].changes, '1,2')
1719 self.assertEqual(self.history[3].result, 'SUCCESS')
1720 self.assertEqual(self.history[3].changes, '1,1 2,2')
1721
1722 def test_abandoned_gate(self):
1723 "Test that an abandoned change is dequeued from gate"
1724
1725 self.worker.hold_jobs_in_build = True
1726
1727 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1728 A.addApproval('CRVW', 2)
1729 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1730 self.waitUntilSettled()
Antoine Mussobd86a312014-01-08 14:51:33 +01001731 self.assertEqual(len(self.builds), 1, "One job being built (on hold)")
1732 self.assertEqual(self.builds[0].name, 'project-merge')
1733
1734 self.fake_gerrit.addEvent(A.getChangeAbandonedEvent())
1735 self.waitUntilSettled()
1736
Antoine Mussobd86a312014-01-08 14:51:33 +01001737 self.worker.release('.*-merge')
1738 self.waitUntilSettled()
1739
1740 self.assertEqual(len(self.builds), 0, "No job running")
Antoine Mussobd86a312014-01-08 14:51:33 +01001741 self.assertEqual(len(self.history), 1, "Only one build in history")
1742 self.assertEqual(self.history[0].result, 'ABORTED',
James E. Blairba437362015-02-07 11:41:52 -08001743 "Build should have been aborted")
1744 self.assertEqual(A.reported, 1,
1745 "Abandoned gate change should report only start")
1746
1747 def test_abandoned_check(self):
1748 "Test that an abandoned change is dequeued from check"
1749
1750 self.worker.hold_jobs_in_build = True
1751
1752 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1753 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1754 check_pipeline = self.sched.layout.pipelines['check']
1755
1756 # Add two git-dependent changes
1757 B.setDependsOn(A, 1)
1758 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1759 self.waitUntilSettled()
1760 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1761 self.waitUntilSettled()
1762 # A live item, and a non-live/live pair
1763 items = check_pipeline.getAllItems()
1764 self.assertEqual(len(items), 3)
1765
1766 self.assertEqual(items[0].change.number, '1')
1767 self.assertFalse(items[0].live)
1768
1769 self.assertEqual(items[1].change.number, '2')
1770 self.assertTrue(items[1].live)
1771
1772 self.assertEqual(items[2].change.number, '1')
1773 self.assertTrue(items[2].live)
1774
1775 # Abandon A
1776 self.fake_gerrit.addEvent(A.getChangeAbandonedEvent())
1777 self.waitUntilSettled()
1778
1779 # The live copy of A should be gone, but the non-live and B
1780 # should continue
1781 items = check_pipeline.getAllItems()
1782 self.assertEqual(len(items), 2)
1783
1784 self.assertEqual(items[0].change.number, '1')
1785 self.assertFalse(items[0].live)
1786
1787 self.assertEqual(items[1].change.number, '2')
1788 self.assertTrue(items[1].live)
1789
1790 self.worker.hold_jobs_in_build = False
1791 self.worker.release()
1792 self.waitUntilSettled()
1793
1794 self.assertEqual(len(self.history), 4)
1795 self.assertEqual(self.history[0].result, 'ABORTED',
Antoine Mussobd86a312014-01-08 14:51:33 +01001796 'Build should have been aborted')
1797 self.assertEqual(A.reported, 0, "Abandoned change should not report")
James E. Blairba437362015-02-07 11:41:52 -08001798 self.assertEqual(B.reported, 1, "Change should report")
Antoine Mussobd86a312014-01-08 14:51:33 +01001799
Steve Varnau7b78b312015-04-03 14:49:46 -07001800 def test_abandoned_not_timer(self):
1801 "Test that an abandoned change does not cancel timer jobs"
1802
1803 self.worker.hold_jobs_in_build = True
1804
1805 # Start timer trigger - also org/project
1806 self.config.set('zuul', 'layout_config',
1807 'tests/fixtures/layout-idle.yaml')
1808 self.sched.reconfigure(self.config)
1809 self.registerJobs()
1810 # The pipeline triggers every second, so we should have seen
1811 # several by now.
1812 time.sleep(5)
1813 self.waitUntilSettled()
1814 # Stop queuing timer triggered jobs so that the assertions
1815 # below don't race against more jobs being queued.
1816 self.config.set('zuul', 'layout_config',
1817 'tests/fixtures/layout-no-timer.yaml')
1818 self.sched.reconfigure(self.config)
1819 self.registerJobs()
1820 self.assertEqual(len(self.builds), 2, "Two timer jobs")
1821
1822 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1823 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1824 self.waitUntilSettled()
1825 self.assertEqual(len(self.builds), 3, "One change plus two timer jobs")
1826
1827 self.fake_gerrit.addEvent(A.getChangeAbandonedEvent())
1828 self.waitUntilSettled()
1829
1830 self.assertEqual(len(self.builds), 2, "Two timer jobs remain")
1831
1832 self.worker.release()
1833 self.waitUntilSettled()
1834
Arx Cruzb1b010d2013-10-28 19:49:59 -02001835 def test_zuul_url_return(self):
1836 "Test if ZUUL_URL is returning when zuul_url is set in zuul.conf"
James E. Blair4076e2b2014-01-28 12:42:20 -08001837 self.assertTrue(self.sched.config.has_option('merger', 'zuul_url'))
Arx Cruzb1b010d2013-10-28 19:49:59 -02001838 self.worker.hold_jobs_in_build = True
1839
1840 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1841 A.addApproval('CRVW', 2)
1842 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1843 self.waitUntilSettled()
1844
1845 self.assertEqual(len(self.builds), 1)
1846 for build in self.builds:
1847 self.assertTrue('ZUUL_URL' in build.parameters)
1848
1849 self.worker.hold_jobs_in_build = False
1850 self.worker.release()
1851 self.waitUntilSettled()
1852
James E. Blair2fa50962013-01-30 21:50:41 -08001853 def test_new_patchset_dequeues_old_on_head(self):
1854 "Test that a new patchset causes the old to be dequeued (at head)"
1855 # D -> C (depends on B) -> B (depends on A) -> A -> M
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001856 self.worker.hold_jobs_in_build = True
James E. Blair2fa50962013-01-30 21:50:41 -08001857 M = self.fake_gerrit.addFakeChange('org/project', 'master', 'M')
1858 M.setMerged()
1859 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1860 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1861 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1862 D = self.fake_gerrit.addFakeChange('org/project', 'master', 'D')
1863 A.addApproval('CRVW', 2)
1864 B.addApproval('CRVW', 2)
1865 C.addApproval('CRVW', 2)
1866 D.addApproval('CRVW', 2)
1867
1868 C.setDependsOn(B, 1)
1869 B.setDependsOn(A, 1)
1870 A.setDependsOn(M, 1)
1871
1872 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1873 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1874 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1875 self.fake_gerrit.addEvent(D.addApproval('APRV', 1))
1876 self.waitUntilSettled()
1877
1878 A.addPatchset()
1879 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
1880 self.waitUntilSettled()
1881
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001882 self.worker.hold_jobs_in_build = False
1883 self.worker.release()
James E. Blair2fa50962013-01-30 21:50:41 -08001884 self.waitUntilSettled()
1885
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001886 self.assertEqual(A.data['status'], 'NEW')
1887 self.assertEqual(A.reported, 2)
1888 self.assertEqual(B.data['status'], 'NEW')
1889 self.assertEqual(B.reported, 2)
1890 self.assertEqual(C.data['status'], 'NEW')
1891 self.assertEqual(C.reported, 2)
1892 self.assertEqual(D.data['status'], 'MERGED')
1893 self.assertEqual(D.reported, 2)
1894 self.assertEqual(len(self.history), 7)
James E. Blair2fa50962013-01-30 21:50:41 -08001895
1896 def test_new_patchset_dequeues_old_without_dependents(self):
1897 "Test that a new patchset causes only the old to be dequeued"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001898 self.worker.hold_jobs_in_build = True
James E. Blair2fa50962013-01-30 21:50:41 -08001899 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1900 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1901 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1902 A.addApproval('CRVW', 2)
1903 B.addApproval('CRVW', 2)
1904 C.addApproval('CRVW', 2)
1905
1906 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1907 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1908 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1909 self.waitUntilSettled()
1910
1911 B.addPatchset()
1912 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(2))
1913 self.waitUntilSettled()
1914
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001915 self.worker.hold_jobs_in_build = False
1916 self.worker.release()
James E. Blair2fa50962013-01-30 21:50:41 -08001917 self.waitUntilSettled()
1918
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001919 self.assertEqual(A.data['status'], 'MERGED')
1920 self.assertEqual(A.reported, 2)
1921 self.assertEqual(B.data['status'], 'NEW')
1922 self.assertEqual(B.reported, 2)
1923 self.assertEqual(C.data['status'], 'MERGED')
1924 self.assertEqual(C.reported, 2)
1925 self.assertEqual(len(self.history), 9)
James E. Blair2fa50962013-01-30 21:50:41 -08001926
1927 def test_new_patchset_dequeues_old_independent_queue(self):
1928 "Test that a new patchset causes the old to be dequeued (independent)"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001929 self.worker.hold_jobs_in_build = True
James E. Blair2fa50962013-01-30 21:50:41 -08001930 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1931 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1932 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1933 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1934 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1935 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
1936 self.waitUntilSettled()
1937
1938 B.addPatchset()
1939 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(2))
1940 self.waitUntilSettled()
1941
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001942 self.worker.hold_jobs_in_build = False
1943 self.worker.release()
James E. Blair2fa50962013-01-30 21:50:41 -08001944 self.waitUntilSettled()
1945
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001946 self.assertEqual(A.data['status'], 'NEW')
1947 self.assertEqual(A.reported, 1)
1948 self.assertEqual(B.data['status'], 'NEW')
1949 self.assertEqual(B.reported, 1)
1950 self.assertEqual(C.data['status'], 'NEW')
1951 self.assertEqual(C.reported, 1)
1952 self.assertEqual(len(self.history), 10)
1953 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 1)
James E. Blair7d0dedc2013-02-21 17:26:09 -08001954
James E. Blair18c64442014-03-18 10:14:45 -07001955 def test_noop_job(self):
1956 "Test that the internal noop job works"
1957 A = self.fake_gerrit.addFakeChange('org/noop-project', 'master', 'A')
1958 A.addApproval('CRVW', 2)
1959 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1960 self.waitUntilSettled()
1961
1962 self.assertEqual(len(self.gearman_server.getQueue()), 0)
1963 self.assertTrue(self.sched._areAllBuildsComplete())
1964 self.assertEqual(len(self.history), 0)
1965 self.assertEqual(A.data['status'], 'MERGED')
1966 self.assertEqual(A.reported, 2)
1967
Evgeny Antyshevd6e546c2015-06-11 15:13:57 +00001968 def test_no_job_project(self):
1969 "Test that reports with no jobs don't get sent"
1970 A = self.fake_gerrit.addFakeChange('org/no-jobs-project',
1971 'master', 'A')
1972 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1973 self.waitUntilSettled()
1974
1975 # Change wasn't reported to
1976 self.assertEqual(A.reported, False)
1977
1978 # Check queue is empty afterwards
1979 check_pipeline = self.sched.layout.pipelines['check']
1980 items = check_pipeline.getAllItems()
1981 self.assertEqual(len(items), 0)
1982
1983 self.assertEqual(len(self.history), 0)
1984
James E. Blair7d0dedc2013-02-21 17:26:09 -08001985 def test_zuul_refs(self):
1986 "Test that zuul refs exist and have the right changes"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001987 self.worker.hold_jobs_in_build = True
James E. Blair7d0dedc2013-02-21 17:26:09 -08001988 M1 = self.fake_gerrit.addFakeChange('org/project1', 'master', 'M1')
1989 M1.setMerged()
1990 M2 = self.fake_gerrit.addFakeChange('org/project2', 'master', 'M2')
1991 M2.setMerged()
1992
1993 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
1994 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
1995 C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
1996 D = self.fake_gerrit.addFakeChange('org/project2', 'master', 'D')
1997 A.addApproval('CRVW', 2)
1998 B.addApproval('CRVW', 2)
1999 C.addApproval('CRVW', 2)
2000 D.addApproval('CRVW', 2)
2001 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2002 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2003 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
2004 self.fake_gerrit.addEvent(D.addApproval('APRV', 1))
2005
2006 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002007 self.worker.release('.*-merge')
James E. Blair7d0dedc2013-02-21 17:26:09 -08002008 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002009 self.worker.release('.*-merge')
James E. Blair7d0dedc2013-02-21 17:26:09 -08002010 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002011 self.worker.release('.*-merge')
James E. Blair7d0dedc2013-02-21 17:26:09 -08002012 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002013 self.worker.release('.*-merge')
James E. Blair7d0dedc2013-02-21 17:26:09 -08002014 self.waitUntilSettled()
2015
James E. Blair7d0dedc2013-02-21 17:26:09 -08002016 a_zref = b_zref = c_zref = d_zref = None
Monty Taylor6bef8ef2013-06-02 08:17:12 -04002017 for x in self.builds:
James E. Blair7d0dedc2013-02-21 17:26:09 -08002018 if x.parameters['ZUUL_CHANGE'] == '3':
2019 a_zref = x.parameters['ZUUL_REF']
2020 if x.parameters['ZUUL_CHANGE'] == '4':
2021 b_zref = x.parameters['ZUUL_REF']
2022 if x.parameters['ZUUL_CHANGE'] == '5':
2023 c_zref = x.parameters['ZUUL_REF']
2024 if x.parameters['ZUUL_CHANGE'] == '6':
2025 d_zref = x.parameters['ZUUL_REF']
2026
2027 # There are... four... refs.
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002028 self.assertIsNotNone(a_zref)
2029 self.assertIsNotNone(b_zref)
2030 self.assertIsNotNone(c_zref)
2031 self.assertIsNotNone(d_zref)
James E. Blair7d0dedc2013-02-21 17:26:09 -08002032
2033 # And they should all be different
2034 refs = set([a_zref, b_zref, c_zref, d_zref])
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002035 self.assertEqual(len(refs), 4)
James E. Blair7d0dedc2013-02-21 17:26:09 -08002036
2037 # a ref should have a, not b, and should not be in project2
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002038 self.assertTrue(self.ref_has_change(a_zref, A))
2039 self.assertFalse(self.ref_has_change(a_zref, B))
2040 self.assertFalse(self.ref_has_change(a_zref, M2))
James E. Blair7d0dedc2013-02-21 17:26:09 -08002041
2042 # b ref should have a and b, and should not be in project2
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002043 self.assertTrue(self.ref_has_change(b_zref, A))
2044 self.assertTrue(self.ref_has_change(b_zref, B))
2045 self.assertFalse(self.ref_has_change(b_zref, M2))
James E. Blair7d0dedc2013-02-21 17:26:09 -08002046
2047 # c ref should have a and b in 1, c in 2
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002048 self.assertTrue(self.ref_has_change(c_zref, A))
2049 self.assertTrue(self.ref_has_change(c_zref, B))
2050 self.assertTrue(self.ref_has_change(c_zref, C))
2051 self.assertFalse(self.ref_has_change(c_zref, D))
James E. Blair7d0dedc2013-02-21 17:26:09 -08002052
2053 # d ref should have a and b in 1, c and d in 2
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002054 self.assertTrue(self.ref_has_change(d_zref, A))
2055 self.assertTrue(self.ref_has_change(d_zref, B))
2056 self.assertTrue(self.ref_has_change(d_zref, C))
2057 self.assertTrue(self.ref_has_change(d_zref, D))
James E. Blair7d0dedc2013-02-21 17:26:09 -08002058
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002059 self.worker.hold_jobs_in_build = False
2060 self.worker.release()
James E. Blair7d0dedc2013-02-21 17:26:09 -08002061 self.waitUntilSettled()
2062
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002063 self.assertEqual(A.data['status'], 'MERGED')
2064 self.assertEqual(A.reported, 2)
2065 self.assertEqual(B.data['status'], 'MERGED')
2066 self.assertEqual(B.reported, 2)
2067 self.assertEqual(C.data['status'], 'MERGED')
2068 self.assertEqual(C.reported, 2)
2069 self.assertEqual(D.data['status'], 'MERGED')
2070 self.assertEqual(D.reported, 2)
James E. Blair70c71582013-03-06 08:50:50 -08002071
James E. Blair4a28a882013-08-23 15:17:33 -07002072 def test_rerun_on_error(self):
2073 "Test that if a worker fails to run a job, it is run again"
2074 self.worker.hold_jobs_in_build = True
2075 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2076 A.addApproval('CRVW', 2)
2077 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2078 self.waitUntilSettled()
2079
2080 self.builds[0].run_error = True
2081 self.worker.hold_jobs_in_build = False
2082 self.worker.release()
2083 self.waitUntilSettled()
2084 self.assertEqual(self.countJobResults(self.history, 'RUN_ERROR'), 1)
2085 self.assertEqual(self.countJobResults(self.history, 'SUCCESS'), 3)
2086
James E. Blair412e5582013-04-22 15:50:12 -07002087 def test_statsd(self):
2088 "Test each of the statsd methods used in the scheduler"
2089 import extras
2090 statsd = extras.try_import('statsd.statsd')
2091 statsd.incr('test-incr')
2092 statsd.timing('test-timing', 3)
Alex Gaynor813d39b2014-05-17 16:17:16 -07002093 statsd.gauge('test-gauge', 12)
James E. Blair412e5582013-04-22 15:50:12 -07002094 self.assertReportedStat('test-incr', '1|c')
2095 self.assertReportedStat('test-timing', '3|ms')
Alex Gaynor813d39b2014-05-17 16:17:16 -07002096 self.assertReportedStat('test-gauge', '12|g')
James E. Blair412e5582013-04-22 15:50:12 -07002097
James E. Blairdad52252014-02-07 16:59:17 -08002098 def test_stuck_job_cleanup(self):
2099 "Test that pending jobs are cleaned up if removed from layout"
James E. Blair18c64442014-03-18 10:14:45 -07002100 # This job won't be registered at startup because it is not in
2101 # the standard layout, but we need it to already be registerd
2102 # for when we reconfigure, as that is when Zuul will attempt
2103 # to run the new job.
2104 self.worker.registerFunction('build:gate-noop')
James E. Blairdad52252014-02-07 16:59:17 -08002105 self.gearman_server.hold_jobs_in_queue = True
2106 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2107 A.addApproval('CRVW', 2)
2108 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2109 self.waitUntilSettled()
2110 self.assertEqual(len(self.gearman_server.getQueue()), 1)
2111
2112 self.config.set('zuul', 'layout_config',
2113 'tests/fixtures/layout-no-jobs.yaml')
2114 self.sched.reconfigure(self.config)
2115 self.waitUntilSettled()
2116
James E. Blair18c64442014-03-18 10:14:45 -07002117 self.gearman_server.release('gate-noop')
James E. Blairdad52252014-02-07 16:59:17 -08002118 self.waitUntilSettled()
2119 self.assertEqual(len(self.gearman_server.getQueue()), 0)
2120 self.assertTrue(self.sched._areAllBuildsComplete())
2121
2122 self.assertEqual(len(self.history), 1)
James E. Blair18c64442014-03-18 10:14:45 -07002123 self.assertEqual(self.history[0].name, 'gate-noop')
James E. Blairdad52252014-02-07 16:59:17 -08002124 self.assertEqual(self.history[0].result, 'SUCCESS')
2125
James E. Blair879dafb2015-07-17 14:04:49 -07002126 def test_file_head(self):
2127 # This is a regression test for an observed bug. A change
2128 # with a file named "HEAD" in the root directory of the repo
2129 # was processed by a merger. It then was unable to reset the
2130 # repo because of:
2131 # GitCommandError: 'git reset --hard HEAD' returned
2132 # with exit code 128
2133 # stderr: 'fatal: ambiguous argument 'HEAD': both revision
2134 # and filename
2135 # Use '--' to separate filenames from revisions'
2136
2137 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2138 A.addPatchset(['HEAD'])
2139 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2140
2141 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
2142 self.waitUntilSettled()
2143
2144 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2145 self.waitUntilSettled()
2146
2147 self.assertIn('Build succeeded', A.messages[0])
2148 self.assertIn('Build succeeded', B.messages[0])
2149
James E. Blair70c71582013-03-06 08:50:50 -08002150 def test_file_jobs(self):
2151 "Test that file jobs run only when appropriate"
2152 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2153 A.addPatchset(['pip-requires'])
2154 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2155 A.addApproval('CRVW', 2)
2156 B.addApproval('CRVW', 2)
2157 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2158 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2159 self.waitUntilSettled()
2160
Monty Taylor6bef8ef2013-06-02 08:17:12 -04002161 testfile_jobs = [x for x in self.history
James E. Blair70c71582013-03-06 08:50:50 -08002162 if x.name == 'project-testfile']
2163
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002164 self.assertEqual(len(testfile_jobs), 1)
2165 self.assertEqual(testfile_jobs[0].changes, '1,2')
2166 self.assertEqual(A.data['status'], 'MERGED')
2167 self.assertEqual(A.reported, 2)
2168 self.assertEqual(B.data['status'], 'MERGED')
2169 self.assertEqual(B.reported, 2)
James E. Blair3c5e5b52013-04-26 11:17:03 -07002170
Maru Newby3fe5f852015-01-13 04:22:14 +00002171 def _test_skip_if_jobs(self, branch, should_skip):
2172 "Test that jobs with a skip-if filter run only when appropriate"
2173 self.config.set('zuul', 'layout_config',
2174 'tests/fixtures/layout-skip-if.yaml')
2175 self.sched.reconfigure(self.config)
2176 self.registerJobs()
2177
2178 change = self.fake_gerrit.addFakeChange('org/project',
2179 branch,
2180 'test skip-if')
2181 self.fake_gerrit.addEvent(change.getPatchsetCreatedEvent(1))
2182 self.waitUntilSettled()
2183
2184 tested_change_ids = [x.changes[0] for x in self.history
2185 if x.name == 'project-test-skip-if']
2186
2187 if should_skip:
2188 self.assertEqual([], tested_change_ids)
2189 else:
2190 self.assertIn(change.data['number'], tested_change_ids)
2191
2192 def test_skip_if_match_skips_job(self):
2193 self._test_skip_if_jobs(branch='master', should_skip=True)
2194
2195 def test_skip_if_no_match_runs_job(self):
2196 self._test_skip_if_jobs(branch='mp', should_skip=False)
2197
James E. Blair3c5e5b52013-04-26 11:17:03 -07002198 def test_test_config(self):
2199 "Test that we can test the config"
Joshua Hesketh352264b2015-08-11 23:42:08 +10002200 self.sched.testConfig(self.config.get('zuul', 'layout_config'),
2201 self.connections)
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002202
2203 def test_build_description(self):
2204 "Test that build descriptions update"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002205 self.worker.registerFunction('set_description:' +
2206 self.worker.worker_id)
2207
2208 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2209 A.addApproval('CRVW', 2)
2210 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2211 self.waitUntilSettled()
Monty Taylor6bef8ef2013-06-02 08:17:12 -04002212 desc = self.history[0].description
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002213 self.log.debug("Description: %s" % desc)
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002214 self.assertTrue(re.search("Branch.*master", desc))
2215 self.assertTrue(re.search("Pipeline.*gate", desc))
2216 self.assertTrue(re.search("project-merge.*SUCCESS", desc))
2217 self.assertTrue(re.search("project-test1.*SUCCESS", desc))
2218 self.assertTrue(re.search("project-test2.*SUCCESS", desc))
2219 self.assertTrue(re.search("Reported result.*SUCCESS", desc))
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002220
James E. Blairc8a1e052014-02-25 09:29:26 -08002221 def test_queue_names(self):
2222 "Test shared change queue names"
2223 project1 = self.sched.layout.projects['org/project1']
2224 project2 = self.sched.layout.projects['org/project2']
2225 q1 = self.sched.layout.pipelines['gate'].getQueue(project1)
2226 q2 = self.sched.layout.pipelines['gate'].getQueue(project2)
2227 self.assertEqual(q1.name, 'integration')
2228 self.assertEqual(q2.name, 'integration')
2229
2230 self.config.set('zuul', 'layout_config',
2231 'tests/fixtures/layout-bad-queue.yaml')
2232 with testtools.ExpectedException(
2233 Exception, "More than one name assigned to change queue"):
2234 self.sched.reconfigure(self.config)
2235
James E. Blair64ed6f22013-07-10 14:07:23 -07002236 def test_queue_precedence(self):
2237 "Test that queue precedence works"
2238
2239 self.gearman_server.hold_jobs_in_queue = True
James E. Blair8de58bd2013-07-18 16:23:33 -07002240 self.worker.hold_jobs_in_build = True
James E. Blair64ed6f22013-07-10 14:07:23 -07002241 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2242 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2243 A.addApproval('CRVW', 2)
2244 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2245
2246 self.waitUntilSettled()
2247 self.gearman_server.hold_jobs_in_queue = False
2248 self.gearman_server.release()
2249 self.waitUntilSettled()
2250
James E. Blair8de58bd2013-07-18 16:23:33 -07002251 # Run one build at a time to ensure non-race order:
James E. Blairb8c16472015-05-05 14:55:26 -07002252 self.orderedRelease()
James E. Blair8de58bd2013-07-18 16:23:33 -07002253 self.worker.hold_jobs_in_build = False
2254 self.waitUntilSettled()
2255
James E. Blair64ed6f22013-07-10 14:07:23 -07002256 self.log.debug(self.history)
2257 self.assertEqual(self.history[0].pipeline, 'gate')
2258 self.assertEqual(self.history[1].pipeline, 'check')
2259 self.assertEqual(self.history[2].pipeline, 'gate')
2260 self.assertEqual(self.history[3].pipeline, 'gate')
2261 self.assertEqual(self.history[4].pipeline, 'check')
2262 self.assertEqual(self.history[5].pipeline, 'check')
2263
Clark Boylana5edbe42014-06-03 16:39:10 -07002264 def test_json_status(self):
James E. Blair1843a552013-07-03 14:19:52 -07002265 "Test that we can retrieve JSON status info"
2266 self.worker.hold_jobs_in_build = True
2267 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2268 A.addApproval('CRVW', 2)
2269 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2270 self.waitUntilSettled()
2271
James E. Blairb7273ef2016-04-19 08:58:51 -07002272 self.worker.release('project-merge')
2273 self.waitUntilSettled()
2274
James E. Blair1843a552013-07-03 14:19:52 -07002275 port = self.webapp.server.socket.getsockname()[1]
2276
Morgan Fainberg293f7f82016-05-30 14:01:22 -07002277 req = urllib.request.Request("http://localhost:%s/status.json" % port)
2278 f = urllib.request.urlopen(req)
Clark Boylanaa4f2e72014-06-03 21:22:40 -07002279 headers = f.info()
2280 self.assertIn('Content-Length', headers)
2281 self.assertIn('Content-Type', headers)
Sachi Kingdc963fc2016-03-23 16:00:33 +11002282 self.assertIsNotNone(re.match('^application/json(; charset=UTF-8)?$',
2283 headers['Content-Type']))
Timo Tijhof0ebd2932015-04-02 12:11:21 +01002284 self.assertIn('Access-Control-Allow-Origin', headers)
2285 self.assertIn('Cache-Control', headers)
Clark Boylanaa4f2e72014-06-03 21:22:40 -07002286 self.assertIn('Last-Modified', headers)
Timo Tijhof0ebd2932015-04-02 12:11:21 +01002287 self.assertIn('Expires', headers)
James E. Blair1843a552013-07-03 14:19:52 -07002288 data = f.read()
2289
2290 self.worker.hold_jobs_in_build = False
2291 self.worker.release()
2292 self.waitUntilSettled()
2293
2294 data = json.loads(data)
James E. Blairb7273ef2016-04-19 08:58:51 -07002295 status_jobs = []
James E. Blair1843a552013-07-03 14:19:52 -07002296 for p in data['pipelines']:
2297 for q in p['change_queues']:
James E. Blairbfb8e042014-12-30 17:01:44 -08002298 if p['name'] in ['gate', 'conflict']:
Clark Boylanaf2476f2014-01-23 14:47:36 -08002299 self.assertEqual(q['window'], 20)
2300 else:
2301 self.assertEqual(q['window'], 0)
James E. Blair1843a552013-07-03 14:19:52 -07002302 for head in q['heads']:
2303 for change in head:
Clark Boylanaf2476f2014-01-23 14:47:36 -08002304 self.assertTrue(change['active'])
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002305 self.assertEqual(change['id'], '1,1')
James E. Blair1843a552013-07-03 14:19:52 -07002306 for job in change['jobs']:
James E. Blairb7273ef2016-04-19 08:58:51 -07002307 status_jobs.append(job)
2308 self.assertEqual('project-merge', status_jobs[0]['name'])
2309 self.assertEqual('https://server/job/project-merge/0/',
2310 status_jobs[0]['url'])
2311 self.assertEqual('http://logs.example.com/1/1/gate/project-merge/0',
2312 status_jobs[0]['report_url'])
2313
2314 self.assertEqual('project-test1', status_jobs[1]['name'])
2315 self.assertEqual('https://server/job/project-test1/1/',
2316 status_jobs[1]['url'])
2317 self.assertEqual('http://logs.example.com/1/1/gate/project-test1/1',
2318 status_jobs[1]['report_url'])
2319
2320 self.assertEqual('project-test2', status_jobs[2]['name'])
2321 self.assertEqual('https://server/job/project-test2/2/',
2322 status_jobs[2]['url'])
2323 self.assertEqual('http://logs.example.com/1/1/gate/project-test2/2',
2324 status_jobs[2]['report_url'])
James E. Blair1843a552013-07-03 14:19:52 -07002325
James E. Blairc3d428e2013-12-03 15:06:48 -08002326 def test_merging_queues(self):
2327 "Test that transitively-connected change queues are merged"
2328 self.config.set('zuul', 'layout_config',
2329 'tests/fixtures/layout-merge-queues.yaml')
2330 self.sched.reconfigure(self.config)
2331 self.assertEqual(len(self.sched.layout.pipelines['gate'].queues), 1)
2332
James E. Blairaf17a972016-02-03 15:07:18 -08002333 def test_mutex(self):
2334 "Test job mutexes"
2335 self.config.set('zuul', 'layout_config',
2336 'tests/fixtures/layout-mutex.yaml')
2337 self.sched.reconfigure(self.config)
2338
2339 self.worker.hold_jobs_in_build = True
2340 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2341 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2342 self.assertFalse('test-mutex' in self.sched.mutex.mutexes)
2343
2344 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2345 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2346 self.waitUntilSettled()
2347 self.assertEqual(len(self.builds), 3)
2348 self.assertEqual(self.builds[0].name, 'project-test1')
2349 self.assertEqual(self.builds[1].name, 'mutex-one')
2350 self.assertEqual(self.builds[2].name, 'project-test1')
2351
2352 self.worker.release('mutex-one')
2353 self.waitUntilSettled()
2354
2355 self.assertEqual(len(self.builds), 3)
2356 self.assertEqual(self.builds[0].name, 'project-test1')
2357 self.assertEqual(self.builds[1].name, 'project-test1')
2358 self.assertEqual(self.builds[2].name, 'mutex-two')
2359 self.assertTrue('test-mutex' in self.sched.mutex.mutexes)
2360
2361 self.worker.release('mutex-two')
2362 self.waitUntilSettled()
2363
2364 self.assertEqual(len(self.builds), 3)
2365 self.assertEqual(self.builds[0].name, 'project-test1')
2366 self.assertEqual(self.builds[1].name, 'project-test1')
2367 self.assertEqual(self.builds[2].name, 'mutex-one')
2368 self.assertTrue('test-mutex' in self.sched.mutex.mutexes)
2369
2370 self.worker.release('mutex-one')
2371 self.waitUntilSettled()
2372
2373 self.assertEqual(len(self.builds), 3)
2374 self.assertEqual(self.builds[0].name, 'project-test1')
2375 self.assertEqual(self.builds[1].name, 'project-test1')
2376 self.assertEqual(self.builds[2].name, 'mutex-two')
2377 self.assertTrue('test-mutex' in self.sched.mutex.mutexes)
2378
2379 self.worker.release('mutex-two')
2380 self.waitUntilSettled()
2381
2382 self.assertEqual(len(self.builds), 2)
2383 self.assertEqual(self.builds[0].name, 'project-test1')
2384 self.assertEqual(self.builds[1].name, 'project-test1')
2385 self.assertFalse('test-mutex' in self.sched.mutex.mutexes)
2386
2387 self.worker.hold_jobs_in_build = False
2388 self.worker.release()
2389
2390 self.waitUntilSettled()
2391 self.assertEqual(len(self.builds), 0)
2392
2393 self.assertEqual(A.reported, 1)
2394 self.assertEqual(B.reported, 1)
2395 self.assertFalse('test-mutex' in self.sched.mutex.mutexes)
2396
Tobias Henkel46237f12016-10-11 07:52:33 +02002397 def test_mutex_abandon(self):
2398 "Test abandon with job mutexes"
2399 self.config.set('zuul', 'layout_config',
2400 'tests/fixtures/layout-mutex.yaml')
2401 self.sched.reconfigure(self.config)
2402
2403 self.worker.hold_jobs_in_build = True
2404
2405 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2406 self.assertFalse('test-mutex' in self.sched.mutex.mutexes)
2407
2408 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2409 self.waitUntilSettled()
2410
2411 self.assertTrue('test-mutex' in self.sched.mutex.mutexes)
2412
2413 self.fake_gerrit.addEvent(A.getChangeAbandonedEvent())
2414 self.waitUntilSettled()
2415
2416 # The check pipeline should be empty
2417 items = self.sched.layout.pipelines['check'].getAllItems()
2418 self.assertEqual(len(items), 0)
2419
2420 # The mutex should be released
2421 self.assertFalse('test-mutex' in self.sched.mutex.mutexes)
2422
2423 def test_mutex_reconfigure(self):
2424 "Test reconfigure with job mutexes"
2425 self.config.set('zuul', 'layout_config',
2426 'tests/fixtures/layout-mutex.yaml')
2427 self.sched.reconfigure(self.config)
2428
2429 self.worker.hold_jobs_in_build = True
2430
2431 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2432 self.assertFalse('test-mutex' in self.sched.mutex.mutexes)
2433
2434 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2435 self.waitUntilSettled()
2436
2437 self.assertTrue('test-mutex' in self.sched.mutex.mutexes)
2438
2439 self.config.set('zuul', 'layout_config',
2440 'tests/fixtures/layout-mutex-reconfiguration.yaml')
2441 self.sched.reconfigure(self.config)
2442 self.waitUntilSettled()
2443
2444 self.worker.release('project-test1')
2445 self.waitUntilSettled()
2446
2447 # The check pipeline should be empty
2448 items = self.sched.layout.pipelines['check'].getAllItems()
2449 self.assertEqual(len(items), 0)
2450
2451 # The mutex should be released
2452 self.assertFalse('test-mutex' in self.sched.mutex.mutexes)
2453
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002454 def test_node_label(self):
2455 "Test that a job runs on a specific node label"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002456 self.worker.registerFunction('build:node-project-test1:debian')
2457
2458 A = self.fake_gerrit.addFakeChange('org/node-project', 'master', 'A')
2459 A.addApproval('CRVW', 2)
2460 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2461 self.waitUntilSettled()
James E. Blair4ca985f2013-05-30 12:27:43 -07002462
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002463 self.assertIsNone(self.getJobFromHistory('node-project-merge').node)
2464 self.assertEqual(self.getJobFromHistory('node-project-test1').node,
2465 'debian')
2466 self.assertIsNone(self.getJobFromHistory('node-project-test2').node)
James E. Blaircdccd972013-07-01 12:10:22 -07002467
2468 def test_live_reconfiguration(self):
2469 "Test that live reconfiguration works"
2470 self.worker.hold_jobs_in_build = True
2471 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2472 A.addApproval('CRVW', 2)
2473 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2474 self.waitUntilSettled()
2475
2476 self.sched.reconfigure(self.config)
2477
2478 self.worker.hold_jobs_in_build = False
2479 self.worker.release()
2480 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002481 self.assertEqual(self.getJobFromHistory('project-merge').result,
2482 'SUCCESS')
2483 self.assertEqual(self.getJobFromHistory('project-test1').result,
2484 'SUCCESS')
2485 self.assertEqual(self.getJobFromHistory('project-test2').result,
2486 'SUCCESS')
2487 self.assertEqual(A.data['status'], 'MERGED')
2488 self.assertEqual(A.reported, 2)
James E. Blair287c06d2013-07-24 10:39:30 -07002489
James E. Blair6bc782d2015-07-17 16:20:21 -07002490 def test_live_reconfiguration_merge_conflict(self):
2491 # A real-world bug: a change in a gate queue has a merge
2492 # conflict and a job is added to its project while it's
2493 # sitting in the queue. The job gets added to the change and
2494 # enqueued and the change gets stuck.
2495 self.worker.registerFunction('build:project-test3')
2496 self.worker.hold_jobs_in_build = True
2497
2498 # This change is fine. It's here to stop the queue long
2499 # enough for the next change to be subject to the
2500 # reconfiguration, as well as to provide a conflict for the
2501 # next change. This change will succeed and merge.
2502 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2503 A.addPatchset(['conflict'])
2504 A.addApproval('CRVW', 2)
James E. Blair6bc782d2015-07-17 16:20:21 -07002505
2506 # This change will be in merge conflict. During the
2507 # reconfiguration, we will add a job. We want to make sure
2508 # that doesn't cause it to get stuck.
2509 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2510 B.addPatchset(['conflict'])
2511 B.addApproval('CRVW', 2)
James E. Blair4eb21fa2015-07-27 14:56:47 -07002512
2513 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
James E. Blair6bc782d2015-07-17 16:20:21 -07002514 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2515
2516 self.waitUntilSettled()
2517
2518 # No jobs have run yet
2519 self.assertEqual(A.data['status'], 'NEW')
2520 self.assertEqual(A.reported, 1)
2521 self.assertEqual(B.data['status'], 'NEW')
2522 self.assertEqual(B.reported, 1)
2523 self.assertEqual(len(self.history), 0)
2524
2525 # Add the "project-test3" job.
2526 self.config.set('zuul', 'layout_config',
2527 'tests/fixtures/layout-live-'
2528 'reconfiguration-add-job.yaml')
2529 self.sched.reconfigure(self.config)
2530 self.waitUntilSettled()
2531
2532 self.worker.hold_jobs_in_build = False
2533 self.worker.release()
2534 self.waitUntilSettled()
2535
2536 self.assertEqual(A.data['status'], 'MERGED')
2537 self.assertEqual(A.reported, 2)
2538 self.assertEqual(B.data['status'], 'NEW')
2539 self.assertEqual(B.reported, 2)
2540 self.assertEqual(self.getJobFromHistory('project-merge').result,
2541 'SUCCESS')
2542 self.assertEqual(self.getJobFromHistory('project-test1').result,
2543 'SUCCESS')
2544 self.assertEqual(self.getJobFromHistory('project-test2').result,
2545 'SUCCESS')
2546 self.assertEqual(self.getJobFromHistory('project-test3').result,
2547 'SUCCESS')
2548 self.assertEqual(len(self.history), 4)
2549
James E. Blair400e8fd2015-07-30 17:44:45 -07002550 def test_live_reconfiguration_failed_root(self):
James E. Blair6bc782d2015-07-17 16:20:21 -07002551 # An extrapolation of test_live_reconfiguration_merge_conflict
2552 # that tests a job added to a job tree with a failed root does
2553 # not run.
2554 self.worker.registerFunction('build:project-test3')
2555 self.worker.hold_jobs_in_build = True
2556
2557 # This change is fine. It's here to stop the queue long
2558 # enough for the next change to be subject to the
2559 # reconfiguration. This change will succeed and merge.
2560 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2561 A.addPatchset(['conflict'])
2562 A.addApproval('CRVW', 2)
2563 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2564 self.waitUntilSettled()
2565 self.worker.release('.*-merge')
2566 self.waitUntilSettled()
2567
2568 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2569 self.worker.addFailTest('project-merge', B)
2570 B.addApproval('CRVW', 2)
2571 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2572 self.waitUntilSettled()
2573
2574 self.worker.release('.*-merge')
2575 self.waitUntilSettled()
2576
2577 # Both -merge jobs have run, but no others.
2578 self.assertEqual(A.data['status'], 'NEW')
2579 self.assertEqual(A.reported, 1)
2580 self.assertEqual(B.data['status'], 'NEW')
2581 self.assertEqual(B.reported, 1)
2582 self.assertEqual(self.history[0].result, 'SUCCESS')
2583 self.assertEqual(self.history[0].name, 'project-merge')
2584 self.assertEqual(self.history[1].result, 'FAILURE')
2585 self.assertEqual(self.history[1].name, 'project-merge')
2586 self.assertEqual(len(self.history), 2)
2587
2588 # Add the "project-test3" job.
2589 self.config.set('zuul', 'layout_config',
2590 'tests/fixtures/layout-live-'
2591 'reconfiguration-add-job.yaml')
2592 self.sched.reconfigure(self.config)
2593 self.waitUntilSettled()
2594
2595 self.worker.hold_jobs_in_build = False
2596 self.worker.release()
2597 self.waitUntilSettled()
2598
2599 self.assertEqual(A.data['status'], 'MERGED')
2600 self.assertEqual(A.reported, 2)
2601 self.assertEqual(B.data['status'], 'NEW')
2602 self.assertEqual(B.reported, 2)
2603 self.assertEqual(self.history[0].result, 'SUCCESS')
2604 self.assertEqual(self.history[0].name, 'project-merge')
2605 self.assertEqual(self.history[1].result, 'FAILURE')
2606 self.assertEqual(self.history[1].name, 'project-merge')
2607 self.assertEqual(self.history[2].result, 'SUCCESS')
2608 self.assertEqual(self.history[3].result, 'SUCCESS')
2609 self.assertEqual(self.history[4].result, 'SUCCESS')
2610 self.assertEqual(len(self.history), 5)
2611
James E. Blair400e8fd2015-07-30 17:44:45 -07002612 def test_live_reconfiguration_failed_job(self):
2613 # Test that a change with a removed failing job does not
2614 # disrupt reconfiguration. If a change has a failed job and
2615 # that job is removed during a reconfiguration, we observed a
2616 # bug where the code to re-set build statuses would run on
2617 # that build and raise an exception because the job no longer
2618 # existed.
2619 self.worker.hold_jobs_in_build = True
2620
2621 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2622
2623 # This change will fail and later be removed by the reconfiguration.
2624 self.worker.addFailTest('project-test1', A)
2625
2626 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2627 self.waitUntilSettled()
2628 self.worker.release('.*-merge')
2629 self.waitUntilSettled()
2630 self.worker.release('project-test1')
2631 self.waitUntilSettled()
2632
2633 self.assertEqual(A.data['status'], 'NEW')
2634 self.assertEqual(A.reported, 0)
2635
2636 self.assertEqual(self.getJobFromHistory('project-merge').result,
2637 'SUCCESS')
2638 self.assertEqual(self.getJobFromHistory('project-test1').result,
2639 'FAILURE')
2640 self.assertEqual(len(self.history), 2)
2641
2642 # Remove the test1 job.
2643 self.config.set('zuul', 'layout_config',
2644 'tests/fixtures/layout-live-'
2645 'reconfiguration-failed-job.yaml')
2646 self.sched.reconfigure(self.config)
2647 self.waitUntilSettled()
2648
2649 self.worker.hold_jobs_in_build = False
2650 self.worker.release()
2651 self.waitUntilSettled()
2652
2653 self.assertEqual(self.getJobFromHistory('project-test2').result,
2654 'SUCCESS')
2655 self.assertEqual(self.getJobFromHistory('project-testfile').result,
2656 'SUCCESS')
2657 self.assertEqual(len(self.history), 4)
2658
2659 self.assertEqual(A.data['status'], 'NEW')
2660 self.assertEqual(A.reported, 1)
2661 self.assertIn('Build succeeded', A.messages[0])
2662 # Ensure the removed job was not included in the report.
2663 self.assertNotIn('project-test1', A.messages[0])
2664
James E. Blairfe707d12015-08-05 15:18:15 -07002665 def test_live_reconfiguration_shared_queue(self):
2666 # Test that a change with a failing job which was removed from
2667 # this project but otherwise still exists in the system does
2668 # not disrupt reconfiguration.
2669
2670 self.worker.hold_jobs_in_build = True
2671
2672 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
2673
2674 self.worker.addFailTest('project1-project2-integration', A)
2675
2676 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2677 self.waitUntilSettled()
2678 self.worker.release('.*-merge')
2679 self.waitUntilSettled()
2680 self.worker.release('project1-project2-integration')
2681 self.waitUntilSettled()
2682
2683 self.assertEqual(A.data['status'], 'NEW')
2684 self.assertEqual(A.reported, 0)
2685
2686 self.assertEqual(self.getJobFromHistory('project1-merge').result,
2687 'SUCCESS')
2688 self.assertEqual(self.getJobFromHistory(
2689 'project1-project2-integration').result, 'FAILURE')
2690 self.assertEqual(len(self.history), 2)
2691
2692 # Remove the integration job.
2693 self.config.set('zuul', 'layout_config',
2694 'tests/fixtures/layout-live-'
2695 'reconfiguration-shared-queue.yaml')
2696 self.sched.reconfigure(self.config)
2697 self.waitUntilSettled()
2698
2699 self.worker.hold_jobs_in_build = False
2700 self.worker.release()
2701 self.waitUntilSettled()
2702
2703 self.assertEqual(self.getJobFromHistory('project1-merge').result,
2704 'SUCCESS')
2705 self.assertEqual(self.getJobFromHistory('project1-test1').result,
2706 'SUCCESS')
2707 self.assertEqual(self.getJobFromHistory('project1-test2').result,
2708 'SUCCESS')
2709 self.assertEqual(self.getJobFromHistory(
2710 'project1-project2-integration').result, 'FAILURE')
2711 self.assertEqual(len(self.history), 4)
2712
2713 self.assertEqual(A.data['status'], 'NEW')
2714 self.assertEqual(A.reported, 1)
2715 self.assertIn('Build succeeded', A.messages[0])
2716 # Ensure the removed job was not included in the report.
2717 self.assertNotIn('project1-project2-integration', A.messages[0])
2718
Joshua Hesketh4bd7da32016-02-17 20:58:47 +11002719 def test_double_live_reconfiguration_shared_queue(self):
2720 # This was a real-world regression. A change is added to
2721 # gate; a reconfigure happens, a second change which depends
2722 # on the first is added, and a second reconfiguration happens.
2723 # Ensure that both changes merge.
2724
2725 # A failure may indicate incorrect caching or cleaning up of
2726 # references during a reconfiguration.
2727 self.worker.hold_jobs_in_build = True
2728
2729 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
2730 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
2731 B.setDependsOn(A, 1)
2732 A.addApproval('CRVW', 2)
2733 B.addApproval('CRVW', 2)
2734
2735 # Add the parent change.
2736 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2737 self.waitUntilSettled()
2738 self.worker.release('.*-merge')
2739 self.waitUntilSettled()
2740
2741 # Reconfigure (with only one change in the pipeline).
2742 self.sched.reconfigure(self.config)
2743 self.waitUntilSettled()
2744
2745 # Add the child change.
2746 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2747 self.waitUntilSettled()
2748 self.worker.release('.*-merge')
2749 self.waitUntilSettled()
2750
2751 # Reconfigure (with both in the pipeline).
2752 self.sched.reconfigure(self.config)
2753 self.waitUntilSettled()
2754
2755 self.worker.hold_jobs_in_build = False
2756 self.worker.release()
2757 self.waitUntilSettled()
2758
2759 self.assertEqual(len(self.history), 8)
2760
2761 self.assertEqual(A.data['status'], 'MERGED')
2762 self.assertEqual(A.reported, 2)
2763 self.assertEqual(B.data['status'], 'MERGED')
2764 self.assertEqual(B.reported, 2)
2765
Evgeny Antyshev0deaaad2015-08-03 20:22:56 +00002766 def test_live_reconfiguration_del_project(self):
2767 # Test project deletion from layout
2768 # while changes are enqueued
2769
2770 self.worker.hold_jobs_in_build = True
2771 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2772 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
2773 C = self.fake_gerrit.addFakeChange('org/project1', 'master', 'C')
2774
2775 # A Depends-On: B
2776 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
2777 A.subject, B.data['id'])
2778 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2779
2780 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2781 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
2782 self.waitUntilSettled()
2783 self.worker.release('.*-merge')
2784 self.waitUntilSettled()
2785 self.assertEqual(len(self.builds), 5)
2786
2787 # This layout defines only org/project, not org/project1
2788 self.config.set('zuul', 'layout_config',
2789 'tests/fixtures/layout-live-'
2790 'reconfiguration-del-project.yaml')
2791 self.sched.reconfigure(self.config)
2792 self.waitUntilSettled()
2793
2794 # Builds for C aborted, builds for A succeed,
2795 # and have change B applied ahead
2796 job_c = self.getJobFromHistory('project1-test1')
2797 self.assertEqual(job_c.changes, '3,1')
2798 self.assertEqual(job_c.result, 'ABORTED')
2799
2800 self.worker.hold_jobs_in_build = False
2801 self.worker.release()
2802 self.waitUntilSettled()
2803
2804 self.assertEqual(self.getJobFromHistory('project-test1').changes,
2805 '2,1 1,1')
2806
2807 self.assertEqual(A.data['status'], 'NEW')
2808 self.assertEqual(B.data['status'], 'NEW')
2809 self.assertEqual(C.data['status'], 'NEW')
2810 self.assertEqual(A.reported, 1)
2811 self.assertEqual(B.reported, 0)
2812 self.assertEqual(C.reported, 0)
2813
2814 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 0)
2815 self.assertIn('Build succeeded', A.messages[0])
2816
James E. Blaire712d9f2013-07-31 11:40:11 -07002817 def test_live_reconfiguration_functions(self):
2818 "Test live reconfiguration with a custom function"
2819 self.worker.registerFunction('build:node-project-test1:debian')
2820 self.worker.registerFunction('build:node-project-test1:wheezy')
2821 A = self.fake_gerrit.addFakeChange('org/node-project', 'master', 'A')
2822 A.addApproval('CRVW', 2)
2823 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2824 self.waitUntilSettled()
2825
2826 self.assertIsNone(self.getJobFromHistory('node-project-merge').node)
2827 self.assertEqual(self.getJobFromHistory('node-project-test1').node,
2828 'debian')
2829 self.assertIsNone(self.getJobFromHistory('node-project-test2').node)
2830
2831 self.config.set('zuul', 'layout_config',
2832 'tests/fixtures/layout-live-'
2833 'reconfiguration-functions.yaml')
2834 self.sched.reconfigure(self.config)
2835 self.worker.build_history = []
2836
2837 B = self.fake_gerrit.addFakeChange('org/node-project', 'master', 'B')
2838 B.addApproval('CRVW', 2)
2839 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2840 self.waitUntilSettled()
2841
2842 self.assertIsNone(self.getJobFromHistory('node-project-merge').node)
2843 self.assertEqual(self.getJobFromHistory('node-project-test1').node,
2844 'wheezy')
2845 self.assertIsNone(self.getJobFromHistory('node-project-test2').node)
2846
James E. Blair287c06d2013-07-24 10:39:30 -07002847 def test_delayed_repo_init(self):
2848 self.config.set('zuul', 'layout_config',
2849 'tests/fixtures/layout-delayed-repo-init.yaml')
2850 self.sched.reconfigure(self.config)
2851
2852 self.init_repo("org/new-project")
2853 A = self.fake_gerrit.addFakeChange('org/new-project', 'master', 'A')
2854
2855 A.addApproval('CRVW', 2)
2856 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2857 self.waitUntilSettled()
2858 self.assertEqual(self.getJobFromHistory('project-merge').result,
2859 'SUCCESS')
2860 self.assertEqual(self.getJobFromHistory('project-test1').result,
2861 'SUCCESS')
2862 self.assertEqual(self.getJobFromHistory('project-test2').result,
2863 'SUCCESS')
2864 self.assertEqual(A.data['status'], 'MERGED')
2865 self.assertEqual(A.reported, 2)
James E. Blair63bb0ef2013-07-29 17:14:51 -07002866
Clark Boylan6dbbc482013-10-18 10:57:31 -07002867 def test_repo_deleted(self):
2868 self.config.set('zuul', 'layout_config',
2869 'tests/fixtures/layout-repo-deleted.yaml')
2870 self.sched.reconfigure(self.config)
2871
2872 self.init_repo("org/delete-project")
2873 A = self.fake_gerrit.addFakeChange('org/delete-project', 'master', 'A')
2874
2875 A.addApproval('CRVW', 2)
2876 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2877 self.waitUntilSettled()
2878 self.assertEqual(self.getJobFromHistory('project-merge').result,
2879 'SUCCESS')
2880 self.assertEqual(self.getJobFromHistory('project-test1').result,
2881 'SUCCESS')
2882 self.assertEqual(self.getJobFromHistory('project-test2').result,
2883 'SUCCESS')
2884 self.assertEqual(A.data['status'], 'MERGED')
2885 self.assertEqual(A.reported, 2)
2886
2887 # Delete org/new-project zuul repo. Should be recloned.
2888 shutil.rmtree(os.path.join(self.git_root, "org/delete-project"))
2889
2890 B = self.fake_gerrit.addFakeChange('org/delete-project', 'master', 'B')
2891
2892 B.addApproval('CRVW', 2)
2893 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2894 self.waitUntilSettled()
2895 self.assertEqual(self.getJobFromHistory('project-merge').result,
2896 'SUCCESS')
2897 self.assertEqual(self.getJobFromHistory('project-test1').result,
2898 'SUCCESS')
2899 self.assertEqual(self.getJobFromHistory('project-test2').result,
2900 'SUCCESS')
2901 self.assertEqual(B.data['status'], 'MERGED')
2902 self.assertEqual(B.reported, 2)
2903
James E. Blair456f2fb2016-02-09 09:29:33 -08002904 def test_tags(self):
2905 "Test job tags"
2906 self.config.set('zuul', 'layout_config',
2907 'tests/fixtures/layout-tags.yaml')
2908 self.sched.reconfigure(self.config)
2909
2910 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
2911 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
2912 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2913 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2914 self.waitUntilSettled()
2915
2916 results = {'project1-merge': 'extratag merge project1',
2917 'project2-merge': 'merge'}
2918
2919 for build in self.history:
2920 self.assertEqual(results.get(build.name, ''),
2921 build.parameters.get('BUILD_TAGS'))
2922
James E. Blair63bb0ef2013-07-29 17:14:51 -07002923 def test_timer(self):
2924 "Test that a periodic job is triggered"
2925 self.worker.hold_jobs_in_build = True
2926 self.config.set('zuul', 'layout_config',
2927 'tests/fixtures/layout-timer.yaml')
2928 self.sched.reconfigure(self.config)
2929 self.registerJobs()
2930
Clark Boylan3ee090a2014-04-03 20:55:09 -07002931 # The pipeline triggers every second, so we should have seen
2932 # several by now.
2933 time.sleep(5)
James E. Blair63bb0ef2013-07-29 17:14:51 -07002934 self.waitUntilSettled()
Clark Boylan3ee090a2014-04-03 20:55:09 -07002935
2936 self.assertEqual(len(self.builds), 2)
2937
James E. Blair63bb0ef2013-07-29 17:14:51 -07002938 port = self.webapp.server.socket.getsockname()[1]
2939
Morgan Fainberg293f7f82016-05-30 14:01:22 -07002940 req = urllib.request.Request("http://localhost:%s/status.json" % port)
2941 f = urllib.request.urlopen(req)
James E. Blair63bb0ef2013-07-29 17:14:51 -07002942 data = f.read()
2943
2944 self.worker.hold_jobs_in_build = False
Clark Boylan3ee090a2014-04-03 20:55:09 -07002945 # Stop queuing timer triggered jobs so that the assertions
2946 # below don't race against more jobs being queued.
2947 self.config.set('zuul', 'layout_config',
2948 'tests/fixtures/layout-no-timer.yaml')
2949 self.sched.reconfigure(self.config)
2950 self.registerJobs()
James E. Blair63bb0ef2013-07-29 17:14:51 -07002951 self.worker.release()
2952 self.waitUntilSettled()
2953
2954 self.assertEqual(self.getJobFromHistory(
2955 'project-bitrot-stable-old').result, 'SUCCESS')
2956 self.assertEqual(self.getJobFromHistory(
2957 'project-bitrot-stable-older').result, 'SUCCESS')
2958
2959 data = json.loads(data)
2960 status_jobs = set()
2961 for p in data['pipelines']:
2962 for q in p['change_queues']:
2963 for head in q['heads']:
2964 for change in head:
Alex Gaynorddb9ef32013-09-16 21:04:58 -07002965 self.assertEqual(change['id'], None)
James E. Blair63bb0ef2013-07-29 17:14:51 -07002966 for job in change['jobs']:
2967 status_jobs.add(job['name'])
2968 self.assertIn('project-bitrot-stable-old', status_jobs)
2969 self.assertIn('project-bitrot-stable-older', status_jobs)
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002970
James E. Blair4f6033c2014-03-27 15:49:09 -07002971 def test_idle(self):
2972 "Test that frequent periodic jobs work"
2973 self.worker.hold_jobs_in_build = True
James E. Blair4f6033c2014-03-27 15:49:09 -07002974
Clark Boylan3ee090a2014-04-03 20:55:09 -07002975 for x in range(1, 3):
2976 # Test that timer triggers periodic jobs even across
2977 # layout config reloads.
2978 # Start timer trigger
2979 self.config.set('zuul', 'layout_config',
2980 'tests/fixtures/layout-idle.yaml')
2981 self.sched.reconfigure(self.config)
2982 self.registerJobs()
James E. Blair995fc0f2016-02-04 16:48:31 -08002983 self.waitUntilSettled()
James E. Blair4f6033c2014-03-27 15:49:09 -07002984
Clark Boylan3ee090a2014-04-03 20:55:09 -07002985 # The pipeline triggers every second, so we should have seen
2986 # several by now.
2987 time.sleep(5)
Clark Boylan3ee090a2014-04-03 20:55:09 -07002988
2989 # Stop queuing timer triggered jobs so that the assertions
2990 # below don't race against more jobs being queued.
2991 self.config.set('zuul', 'layout_config',
2992 'tests/fixtures/layout-no-timer.yaml')
2993 self.sched.reconfigure(self.config)
2994 self.registerJobs()
James E. Blair995fc0f2016-02-04 16:48:31 -08002995 self.waitUntilSettled()
Clark Boylan3ee090a2014-04-03 20:55:09 -07002996
2997 self.assertEqual(len(self.builds), 2)
2998 self.worker.release('.*')
2999 self.waitUntilSettled()
3000 self.assertEqual(len(self.builds), 0)
3001 self.assertEqual(len(self.history), x * 2)
James E. Blair4f6033c2014-03-27 15:49:09 -07003002
Joshua Hesketh5fea8672013-08-19 17:32:01 +10003003 def test_check_smtp_pool(self):
3004 self.config.set('zuul', 'layout_config',
3005 'tests/fixtures/layout-smtp.yaml')
3006 self.sched.reconfigure(self.config)
3007
3008 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3009 self.waitUntilSettled()
3010
3011 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3012 self.waitUntilSettled()
3013
James E. Blairff80a2f2013-12-27 13:24:06 -08003014 self.assertEqual(len(self.smtp_messages), 2)
Joshua Hesketh5fea8672013-08-19 17:32:01 +10003015
3016 # A.messages only holds what FakeGerrit places in it. Thus we
3017 # work on the knowledge of what the first message should be as
3018 # it is only configured to go to SMTP.
3019
3020 self.assertEqual('zuul@example.com',
James E. Blairff80a2f2013-12-27 13:24:06 -08003021 self.smtp_messages[0]['from_email'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10003022 self.assertEqual(['you@example.com'],
James E. Blairff80a2f2013-12-27 13:24:06 -08003023 self.smtp_messages[0]['to_email'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10003024 self.assertEqual('Starting check jobs.',
James E. Blairff80a2f2013-12-27 13:24:06 -08003025 self.smtp_messages[0]['body'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10003026
3027 self.assertEqual('zuul_from@example.com',
James E. Blairff80a2f2013-12-27 13:24:06 -08003028 self.smtp_messages[1]['from_email'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10003029 self.assertEqual(['alternative_me@example.com'],
James E. Blairff80a2f2013-12-27 13:24:06 -08003030 self.smtp_messages[1]['to_email'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10003031 self.assertEqual(A.messages[0],
James E. Blairff80a2f2013-12-27 13:24:06 -08003032 self.smtp_messages[1]['body'])
James E. Blairad28e912013-11-27 10:43:22 -08003033
James E. Blaire5910202013-12-27 09:50:31 -08003034 def test_timer_smtp(self):
3035 "Test that a periodic job is triggered"
Clark Boylan3ee090a2014-04-03 20:55:09 -07003036 self.worker.hold_jobs_in_build = True
James E. Blaire5910202013-12-27 09:50:31 -08003037 self.config.set('zuul', 'layout_config',
3038 'tests/fixtures/layout-timer-smtp.yaml')
3039 self.sched.reconfigure(self.config)
3040 self.registerJobs()
3041
Clark Boylan3ee090a2014-04-03 20:55:09 -07003042 # The pipeline triggers every second, so we should have seen
3043 # several by now.
3044 time.sleep(5)
James E. Blaire5910202013-12-27 09:50:31 -08003045 self.waitUntilSettled()
3046
Clark Boylan3ee090a2014-04-03 20:55:09 -07003047 self.assertEqual(len(self.builds), 2)
3048 self.worker.release('.*')
3049 self.waitUntilSettled()
3050 self.assertEqual(len(self.history), 2)
3051
James E. Blaire5910202013-12-27 09:50:31 -08003052 self.assertEqual(self.getJobFromHistory(
3053 'project-bitrot-stable-old').result, 'SUCCESS')
3054 self.assertEqual(self.getJobFromHistory(
3055 'project-bitrot-stable-older').result, 'SUCCESS')
3056
James E. Blairff80a2f2013-12-27 13:24:06 -08003057 self.assertEqual(len(self.smtp_messages), 1)
James E. Blaire5910202013-12-27 09:50:31 -08003058
3059 # A.messages only holds what FakeGerrit places in it. Thus we
3060 # work on the knowledge of what the first message should be as
3061 # it is only configured to go to SMTP.
3062
3063 self.assertEqual('zuul_from@example.com',
James E. Blairff80a2f2013-12-27 13:24:06 -08003064 self.smtp_messages[0]['from_email'])
James E. Blaire5910202013-12-27 09:50:31 -08003065 self.assertEqual(['alternative_me@example.com'],
James E. Blairff80a2f2013-12-27 13:24:06 -08003066 self.smtp_messages[0]['to_email'])
James E. Blaire5910202013-12-27 09:50:31 -08003067 self.assertIn('Subject: Periodic check for org/project succeeded',
James E. Blairff80a2f2013-12-27 13:24:06 -08003068 self.smtp_messages[0]['headers'])
James E. Blaire5910202013-12-27 09:50:31 -08003069
Clark Boylan3ee090a2014-04-03 20:55:09 -07003070 # Stop queuing timer triggered jobs and let any that may have
3071 # queued through so that end of test assertions pass.
3072 self.config.set('zuul', 'layout_config',
3073 'tests/fixtures/layout-no-timer.yaml')
3074 self.sched.reconfigure(self.config)
3075 self.registerJobs()
James E. Blairf8058972014-08-15 16:09:16 -07003076 self.waitUntilSettled()
Clark Boylan3ee090a2014-04-03 20:55:09 -07003077 self.worker.release('.*')
3078 self.waitUntilSettled()
3079
Evgeny Antyshevda90a502017-02-08 08:42:59 +00003080 def test_timer_sshkey(self):
3081 "Test that a periodic job can setup SSH key authentication"
3082 self.worker.hold_jobs_in_build = True
3083 self.config.set('zuul', 'layout_config',
3084 'tests/fixtures/layout-timer.yaml')
3085 self.sched.reconfigure(self.config)
3086 self.registerJobs()
3087
3088 # The pipeline triggers every second, so we should have seen
3089 # several by now.
3090 time.sleep(5)
3091 self.waitUntilSettled()
3092
3093 self.assertEqual(len(self.builds), 2)
3094
3095 ssh_wrapper = os.path.join(self.git_root, ".ssh_wrapper_gerrit")
3096 self.assertTrue(os.path.isfile(ssh_wrapper))
3097 with open(ssh_wrapper) as f:
3098 ssh_wrapper_content = f.read()
3099 self.assertIn("fake_id_rsa", ssh_wrapper_content)
3100 # In the unit tests Merger runs in the same process,
3101 # so we see its' environment variables
3102 self.assertEqual(os.environ['GIT_SSH'], ssh_wrapper)
3103
3104 self.worker.release('.*')
3105 self.waitUntilSettled()
3106 self.assertEqual(len(self.history), 2)
3107
3108 self.assertEqual(self.getJobFromHistory(
3109 'project-bitrot-stable-old').result, 'SUCCESS')
3110 self.assertEqual(self.getJobFromHistory(
3111 'project-bitrot-stable-older').result, 'SUCCESS')
3112
3113 # Stop queuing timer triggered jobs and let any that may have
3114 # queued through so that end of test assertions pass.
3115 self.config.set('zuul', 'layout_config',
3116 'tests/fixtures/layout-no-timer.yaml')
3117 self.sched.reconfigure(self.config)
3118 self.registerJobs()
3119 self.waitUntilSettled()
3120 self.worker.release('.*')
3121 self.waitUntilSettled()
3122
James E. Blair91e34592015-07-31 16:45:59 -07003123 def test_client_enqueue_change(self):
James E. Blairad28e912013-11-27 10:43:22 -08003124 "Test that the RPC client can enqueue a change"
3125 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3126 A.addApproval('CRVW', 2)
3127 A.addApproval('APRV', 1)
3128
3129 client = zuul.rpcclient.RPCClient('127.0.0.1',
3130 self.gearman_server.port)
3131 r = client.enqueue(pipeline='gate',
3132 project='org/project',
3133 trigger='gerrit',
James E. Blair36658cf2013-12-06 17:53:48 -08003134 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08003135 self.waitUntilSettled()
3136 self.assertEqual(self.getJobFromHistory('project-merge').result,
3137 'SUCCESS')
3138 self.assertEqual(self.getJobFromHistory('project-test1').result,
3139 'SUCCESS')
3140 self.assertEqual(self.getJobFromHistory('project-test2').result,
3141 'SUCCESS')
3142 self.assertEqual(A.data['status'], 'MERGED')
3143 self.assertEqual(A.reported, 2)
3144 self.assertEqual(r, True)
3145
James E. Blair91e34592015-07-31 16:45:59 -07003146 def test_client_enqueue_ref(self):
3147 "Test that the RPC client can enqueue a ref"
3148
3149 client = zuul.rpcclient.RPCClient('127.0.0.1',
3150 self.gearman_server.port)
3151 r = client.enqueue_ref(
3152 pipeline='post',
3153 project='org/project',
3154 trigger='gerrit',
3155 ref='master',
3156 oldrev='90f173846e3af9154517b88543ffbd1691f31366',
3157 newrev='d479a0bfcb34da57a31adb2a595c0cf687812543')
3158 self.waitUntilSettled()
3159 job_names = [x.name for x in self.history]
3160 self.assertEqual(len(self.history), 1)
3161 self.assertIn('project-post', job_names)
3162 self.assertEqual(r, True)
3163
James E. Blairad28e912013-11-27 10:43:22 -08003164 def test_client_enqueue_negative(self):
3165 "Test that the RPC client returns errors"
3166 client = zuul.rpcclient.RPCClient('127.0.0.1',
3167 self.gearman_server.port)
3168 with testtools.ExpectedException(zuul.rpcclient.RPCFailure,
3169 "Invalid project"):
3170 r = client.enqueue(pipeline='gate',
3171 project='project-does-not-exist',
3172 trigger='gerrit',
James E. Blair36658cf2013-12-06 17:53:48 -08003173 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08003174 client.shutdown()
3175 self.assertEqual(r, False)
3176
3177 with testtools.ExpectedException(zuul.rpcclient.RPCFailure,
3178 "Invalid pipeline"):
3179 r = client.enqueue(pipeline='pipeline-does-not-exist',
3180 project='org/project',
3181 trigger='gerrit',
James E. Blair36658cf2013-12-06 17:53:48 -08003182 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08003183 client.shutdown()
3184 self.assertEqual(r, False)
3185
3186 with testtools.ExpectedException(zuul.rpcclient.RPCFailure,
3187 "Invalid trigger"):
3188 r = client.enqueue(pipeline='gate',
3189 project='org/project',
3190 trigger='trigger-does-not-exist',
James E. Blair36658cf2013-12-06 17:53:48 -08003191 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08003192 client.shutdown()
3193 self.assertEqual(r, False)
3194
3195 with testtools.ExpectedException(zuul.rpcclient.RPCFailure,
3196 "Invalid change"):
3197 r = client.enqueue(pipeline='gate',
3198 project='org/project',
3199 trigger='gerrit',
James E. Blair36658cf2013-12-06 17:53:48 -08003200 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08003201 client.shutdown()
3202 self.assertEqual(r, False)
3203
3204 self.waitUntilSettled()
3205 self.assertEqual(len(self.history), 0)
3206 self.assertEqual(len(self.builds), 0)
James E. Blair36658cf2013-12-06 17:53:48 -08003207
3208 def test_client_promote(self):
3209 "Test that the RPC client can promote a change"
3210 self.worker.hold_jobs_in_build = True
3211 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3212 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
3213 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
3214 A.addApproval('CRVW', 2)
3215 B.addApproval('CRVW', 2)
3216 C.addApproval('CRVW', 2)
3217
3218 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3219 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3220 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
3221
3222 self.waitUntilSettled()
3223
Sean Daguef39b9ca2014-01-10 21:34:35 -05003224 items = self.sched.layout.pipelines['gate'].getAllItems()
3225 enqueue_times = {}
3226 for item in items:
3227 enqueue_times[str(item.change)] = item.enqueue_time
3228
James E. Blair36658cf2013-12-06 17:53:48 -08003229 client = zuul.rpcclient.RPCClient('127.0.0.1',
3230 self.gearman_server.port)
3231 r = client.promote(pipeline='gate',
3232 change_ids=['2,1', '3,1'])
3233
Sean Daguef39b9ca2014-01-10 21:34:35 -05003234 # ensure that enqueue times are durable
3235 items = self.sched.layout.pipelines['gate'].getAllItems()
3236 for item in items:
3237 self.assertEqual(
3238 enqueue_times[str(item.change)], item.enqueue_time)
3239
James E. Blair78acec92014-02-06 07:11:32 -08003240 self.waitUntilSettled()
James E. Blair36658cf2013-12-06 17:53:48 -08003241 self.worker.release('.*-merge')
3242 self.waitUntilSettled()
3243 self.worker.release('.*-merge')
3244 self.waitUntilSettled()
3245 self.worker.release('.*-merge')
3246 self.waitUntilSettled()
3247
3248 self.assertEqual(len(self.builds), 6)
3249 self.assertEqual(self.builds[0].name, 'project-test1')
3250 self.assertEqual(self.builds[1].name, 'project-test2')
3251 self.assertEqual(self.builds[2].name, 'project-test1')
3252 self.assertEqual(self.builds[3].name, 'project-test2')
3253 self.assertEqual(self.builds[4].name, 'project-test1')
3254 self.assertEqual(self.builds[5].name, 'project-test2')
3255
3256 self.assertTrue(self.job_has_changes(self.builds[0], B))
3257 self.assertFalse(self.job_has_changes(self.builds[0], A))
3258 self.assertFalse(self.job_has_changes(self.builds[0], C))
3259
3260 self.assertTrue(self.job_has_changes(self.builds[2], B))
3261 self.assertTrue(self.job_has_changes(self.builds[2], C))
3262 self.assertFalse(self.job_has_changes(self.builds[2], A))
3263
3264 self.assertTrue(self.job_has_changes(self.builds[4], B))
3265 self.assertTrue(self.job_has_changes(self.builds[4], C))
3266 self.assertTrue(self.job_has_changes(self.builds[4], A))
3267
3268 self.worker.release()
3269 self.waitUntilSettled()
3270
3271 self.assertEqual(A.data['status'], 'MERGED')
3272 self.assertEqual(A.reported, 2)
3273 self.assertEqual(B.data['status'], 'MERGED')
3274 self.assertEqual(B.reported, 2)
3275 self.assertEqual(C.data['status'], 'MERGED')
3276 self.assertEqual(C.reported, 2)
3277
3278 client.shutdown()
3279 self.assertEqual(r, True)
3280
3281 def test_client_promote_dependent(self):
3282 "Test that the RPC client can promote a dependent change"
3283 # C (depends on B) -> B -> A ; then promote C to get:
3284 # A -> C (depends on B) -> B
3285 self.worker.hold_jobs_in_build = True
3286 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3287 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
3288 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
3289
3290 C.setDependsOn(B, 1)
3291
3292 A.addApproval('CRVW', 2)
3293 B.addApproval('CRVW', 2)
3294 C.addApproval('CRVW', 2)
3295
3296 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3297 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3298 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
3299
3300 self.waitUntilSettled()
3301
3302 client = zuul.rpcclient.RPCClient('127.0.0.1',
3303 self.gearman_server.port)
3304 r = client.promote(pipeline='gate',
3305 change_ids=['3,1'])
3306
James E. Blair78acec92014-02-06 07:11:32 -08003307 self.waitUntilSettled()
James E. Blair36658cf2013-12-06 17:53:48 -08003308 self.worker.release('.*-merge')
3309 self.waitUntilSettled()
3310 self.worker.release('.*-merge')
3311 self.waitUntilSettled()
3312 self.worker.release('.*-merge')
3313 self.waitUntilSettled()
3314
3315 self.assertEqual(len(self.builds), 6)
3316 self.assertEqual(self.builds[0].name, 'project-test1')
3317 self.assertEqual(self.builds[1].name, 'project-test2')
3318 self.assertEqual(self.builds[2].name, 'project-test1')
3319 self.assertEqual(self.builds[3].name, 'project-test2')
3320 self.assertEqual(self.builds[4].name, 'project-test1')
3321 self.assertEqual(self.builds[5].name, 'project-test2')
3322
3323 self.assertTrue(self.job_has_changes(self.builds[0], B))
3324 self.assertFalse(self.job_has_changes(self.builds[0], A))
3325 self.assertFalse(self.job_has_changes(self.builds[0], C))
3326
3327 self.assertTrue(self.job_has_changes(self.builds[2], B))
3328 self.assertTrue(self.job_has_changes(self.builds[2], C))
3329 self.assertFalse(self.job_has_changes(self.builds[2], A))
3330
3331 self.assertTrue(self.job_has_changes(self.builds[4], B))
3332 self.assertTrue(self.job_has_changes(self.builds[4], C))
3333 self.assertTrue(self.job_has_changes(self.builds[4], A))
3334
3335 self.worker.release()
3336 self.waitUntilSettled()
3337
3338 self.assertEqual(A.data['status'], 'MERGED')
3339 self.assertEqual(A.reported, 2)
3340 self.assertEqual(B.data['status'], 'MERGED')
3341 self.assertEqual(B.reported, 2)
3342 self.assertEqual(C.data['status'], 'MERGED')
3343 self.assertEqual(C.reported, 2)
3344
3345 client.shutdown()
3346 self.assertEqual(r, True)
3347
3348 def test_client_promote_negative(self):
3349 "Test that the RPC client returns errors for promotion"
3350 self.worker.hold_jobs_in_build = True
3351 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3352 A.addApproval('CRVW', 2)
3353 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3354 self.waitUntilSettled()
3355
3356 client = zuul.rpcclient.RPCClient('127.0.0.1',
3357 self.gearman_server.port)
3358
3359 with testtools.ExpectedException(zuul.rpcclient.RPCFailure):
3360 r = client.promote(pipeline='nonexistent',
3361 change_ids=['2,1', '3,1'])
3362 client.shutdown()
3363 self.assertEqual(r, False)
3364
3365 with testtools.ExpectedException(zuul.rpcclient.RPCFailure):
3366 r = client.promote(pipeline='gate',
3367 change_ids=['4,1'])
3368 client.shutdown()
3369 self.assertEqual(r, False)
3370
3371 self.worker.hold_jobs_in_build = False
3372 self.worker.release()
3373 self.waitUntilSettled()
Clark Boylan7603a372014-01-21 11:43:20 -08003374
3375 def test_queue_rate_limiting(self):
3376 "Test that DependentPipelines are rate limited with dep across window"
3377 self.config.set('zuul', 'layout_config',
3378 'tests/fixtures/layout-rate-limit.yaml')
3379 self.sched.reconfigure(self.config)
3380 self.worker.hold_jobs_in_build = True
3381 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3382 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
3383 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
3384
3385 C.setDependsOn(B, 1)
3386 self.worker.addFailTest('project-test1', A)
3387
3388 A.addApproval('CRVW', 2)
3389 B.addApproval('CRVW', 2)
3390 C.addApproval('CRVW', 2)
3391
3392 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3393 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3394 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
3395 self.waitUntilSettled()
3396
3397 # Only A and B will have their merge jobs queued because
3398 # window is 2.
3399 self.assertEqual(len(self.builds), 2)
3400 self.assertEqual(self.builds[0].name, 'project-merge')
3401 self.assertEqual(self.builds[1].name, 'project-merge')
3402
3403 self.worker.release('.*-merge')
3404 self.waitUntilSettled()
3405 self.worker.release('.*-merge')
3406 self.waitUntilSettled()
3407
3408 # Only A and B will have their test jobs queued because
3409 # window is 2.
3410 self.assertEqual(len(self.builds), 4)
3411 self.assertEqual(self.builds[0].name, 'project-test1')
3412 self.assertEqual(self.builds[1].name, 'project-test2')
3413 self.assertEqual(self.builds[2].name, 'project-test1')
3414 self.assertEqual(self.builds[3].name, 'project-test2')
3415
3416 self.worker.release('project-.*')
3417 self.waitUntilSettled()
3418
3419 queue = self.sched.layout.pipelines['gate'].queues[0]
3420 # A failed so window is reduced by 1 to 1.
3421 self.assertEqual(queue.window, 1)
3422 self.assertEqual(queue.window_floor, 1)
3423 self.assertEqual(A.data['status'], 'NEW')
3424
3425 # Gate is reset and only B's merge job is queued because
3426 # window shrunk to 1.
3427 self.assertEqual(len(self.builds), 1)
3428 self.assertEqual(self.builds[0].name, 'project-merge')
3429
3430 self.worker.release('.*-merge')
3431 self.waitUntilSettled()
3432
3433 # Only B's test jobs are queued because window is still 1.
3434 self.assertEqual(len(self.builds), 2)
3435 self.assertEqual(self.builds[0].name, 'project-test1')
3436 self.assertEqual(self.builds[1].name, 'project-test2')
3437
3438 self.worker.release('project-.*')
3439 self.waitUntilSettled()
3440
3441 # B was successfully merged so window is increased to 2.
3442 self.assertEqual(queue.window, 2)
3443 self.assertEqual(queue.window_floor, 1)
3444 self.assertEqual(B.data['status'], 'MERGED')
3445
3446 # Only C is left and its merge job is queued.
3447 self.assertEqual(len(self.builds), 1)
3448 self.assertEqual(self.builds[0].name, 'project-merge')
3449
3450 self.worker.release('.*-merge')
3451 self.waitUntilSettled()
3452
3453 # After successful merge job the test jobs for C are queued.
3454 self.assertEqual(len(self.builds), 2)
3455 self.assertEqual(self.builds[0].name, 'project-test1')
3456 self.assertEqual(self.builds[1].name, 'project-test2')
3457
3458 self.worker.release('project-.*')
3459 self.waitUntilSettled()
3460
3461 # C successfully merged so window is bumped to 3.
3462 self.assertEqual(queue.window, 3)
3463 self.assertEqual(queue.window_floor, 1)
3464 self.assertEqual(C.data['status'], 'MERGED')
3465
3466 def test_queue_rate_limiting_dependent(self):
3467 "Test that DependentPipelines are rate limited with dep in window"
3468 self.config.set('zuul', 'layout_config',
3469 'tests/fixtures/layout-rate-limit.yaml')
3470 self.sched.reconfigure(self.config)
3471 self.worker.hold_jobs_in_build = True
3472 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3473 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
3474 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
3475
3476 B.setDependsOn(A, 1)
3477
3478 self.worker.addFailTest('project-test1', A)
3479
3480 A.addApproval('CRVW', 2)
3481 B.addApproval('CRVW', 2)
3482 C.addApproval('CRVW', 2)
3483
3484 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3485 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3486 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
3487 self.waitUntilSettled()
3488
3489 # Only A and B will have their merge jobs queued because
3490 # window is 2.
3491 self.assertEqual(len(self.builds), 2)
3492 self.assertEqual(self.builds[0].name, 'project-merge')
3493 self.assertEqual(self.builds[1].name, 'project-merge')
3494
3495 self.worker.release('.*-merge')
3496 self.waitUntilSettled()
3497 self.worker.release('.*-merge')
3498 self.waitUntilSettled()
3499
3500 # Only A and B will have their test jobs queued because
3501 # window is 2.
3502 self.assertEqual(len(self.builds), 4)
3503 self.assertEqual(self.builds[0].name, 'project-test1')
3504 self.assertEqual(self.builds[1].name, 'project-test2')
3505 self.assertEqual(self.builds[2].name, 'project-test1')
3506 self.assertEqual(self.builds[3].name, 'project-test2')
3507
3508 self.worker.release('project-.*')
3509 self.waitUntilSettled()
3510
3511 queue = self.sched.layout.pipelines['gate'].queues[0]
3512 # A failed so window is reduced by 1 to 1.
3513 self.assertEqual(queue.window, 1)
3514 self.assertEqual(queue.window_floor, 1)
3515 self.assertEqual(A.data['status'], 'NEW')
3516 self.assertEqual(B.data['status'], 'NEW')
3517
3518 # Gate is reset and only C's merge job is queued because
3519 # window shrunk to 1 and A and B were dequeued.
3520 self.assertEqual(len(self.builds), 1)
3521 self.assertEqual(self.builds[0].name, 'project-merge')
3522
3523 self.worker.release('.*-merge')
3524 self.waitUntilSettled()
3525
3526 # Only C's test jobs are queued because window is still 1.
3527 self.assertEqual(len(self.builds), 2)
3528 self.assertEqual(self.builds[0].name, 'project-test1')
3529 self.assertEqual(self.builds[1].name, 'project-test2')
3530
3531 self.worker.release('project-.*')
3532 self.waitUntilSettled()
3533
3534 # C was successfully merged so window is increased to 2.
3535 self.assertEqual(queue.window, 2)
3536 self.assertEqual(queue.window_floor, 1)
3537 self.assertEqual(C.data['status'], 'MERGED')
Joshua Heskethba8776a2014-01-12 14:35:40 +08003538
3539 def test_worker_update_metadata(self):
3540 "Test if a worker can send back metadata about itself"
3541 self.worker.hold_jobs_in_build = True
3542
3543 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3544 A.addApproval('CRVW', 2)
3545 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3546 self.waitUntilSettled()
3547
3548 self.assertEqual(len(self.launcher.builds), 1)
3549
3550 self.log.debug('Current builds:')
3551 self.log.debug(self.launcher.builds)
3552
3553 start = time.time()
3554 while True:
3555 if time.time() - start > 10:
3556 raise Exception("Timeout waiting for gearman server to report "
3557 + "back to the client")
3558 build = self.launcher.builds.values()[0]
3559 if build.worker.name == "My Worker":
3560 break
3561 else:
3562 time.sleep(0)
3563
3564 self.log.debug(build)
3565 self.assertEqual("My Worker", build.worker.name)
3566 self.assertEqual("localhost", build.worker.hostname)
3567 self.assertEqual(['127.0.0.1', '192.168.1.1'], build.worker.ips)
3568 self.assertEqual("zuul.example.org", build.worker.fqdn)
3569 self.assertEqual("FakeBuilder", build.worker.program)
3570 self.assertEqual("v1.1", build.worker.version)
3571 self.assertEqual({'something': 'else'}, build.worker.extra)
3572
3573 self.worker.hold_jobs_in_build = False
3574 self.worker.release()
3575 self.waitUntilSettled()
Joshua Hesketh3979e3e2014-03-04 11:21:10 +11003576
3577 def test_footer_message(self):
3578 "Test a pipeline's footer message is correctly added to the report."
3579 self.config.set('zuul', 'layout_config',
3580 'tests/fixtures/layout-footer-message.yaml')
3581 self.sched.reconfigure(self.config)
3582 self.registerJobs()
3583
3584 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3585 A.addApproval('CRVW', 2)
3586 self.worker.addFailTest('test1', A)
3587 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3588 self.waitUntilSettled()
3589
3590 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
3591 B.addApproval('CRVW', 2)
3592 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3593 self.waitUntilSettled()
3594
3595 self.assertEqual(2, len(self.smtp_messages))
3596
3597 failure_body = """\
3598Build failed. For information on how to proceed, see \
3599http://wiki.example.org/Test_Failures
3600
3601- test1 http://logs.example.com/1/1/gate/test1/0 : FAILURE in 0s
3602- test2 http://logs.example.com/1/1/gate/test2/1 : SUCCESS in 0s
3603
3604For CI problems and help debugging, contact ci@example.org"""
3605
3606 success_body = """\
3607Build succeeded.
3608
3609- test1 http://logs.example.com/2/1/gate/test1/2 : SUCCESS in 0s
3610- test2 http://logs.example.com/2/1/gate/test2/3 : SUCCESS in 0s
3611
3612For CI problems and help debugging, contact ci@example.org"""
3613
3614 self.assertEqual(failure_body, self.smtp_messages[0]['body'])
3615 self.assertEqual(success_body, self.smtp_messages[1]['body'])
Joshua Heskethb7179772014-01-30 23:30:46 +11003616
3617 def test_merge_failure_reporters(self):
3618 """Check that the config is set up correctly"""
3619
3620 self.config.set('zuul', 'layout_config',
3621 'tests/fixtures/layout-merge-failure.yaml')
3622 self.sched.reconfigure(self.config)
3623 self.registerJobs()
3624
3625 self.assertEqual(
Jeremy Stanley1c2c3c22015-06-15 21:23:19 +00003626 "Merge Failed.\n\nThis change or one of its cross-repo "
3627 "dependencies was unable to be automatically merged with the "
3628 "current state of its repository. Please rebase the change and "
3629 "upload a new patchset.",
Joshua Heskethb7179772014-01-30 23:30:46 +11003630 self.sched.layout.pipelines['check'].merge_failure_message)
3631 self.assertEqual(
3632 "The merge failed! For more information...",
3633 self.sched.layout.pipelines['gate'].merge_failure_message)
3634
3635 self.assertEqual(
3636 len(self.sched.layout.pipelines['check'].merge_failure_actions), 1)
3637 self.assertEqual(
3638 len(self.sched.layout.pipelines['gate'].merge_failure_actions), 2)
3639
3640 self.assertTrue(isinstance(
Joshua Heskethde958652015-11-10 19:19:50 +11003641 self.sched.layout.pipelines['check'].merge_failure_actions[0],
3642 zuul.reporter.gerrit.GerritReporter))
Joshua Heskethb7179772014-01-30 23:30:46 +11003643
3644 self.assertTrue(
3645 (
3646 isinstance(self.sched.layout.pipelines['gate'].
Joshua Heskethde958652015-11-10 19:19:50 +11003647 merge_failure_actions[0],
Joshua Heskethffe42062014-09-05 21:43:52 +10003648 zuul.reporter.smtp.SMTPReporter) and
Joshua Heskethb7179772014-01-30 23:30:46 +11003649 isinstance(self.sched.layout.pipelines['gate'].
Joshua Heskethde958652015-11-10 19:19:50 +11003650 merge_failure_actions[1],
Joshua Heskethffe42062014-09-05 21:43:52 +10003651 zuul.reporter.gerrit.GerritReporter)
Joshua Heskethb7179772014-01-30 23:30:46 +11003652 ) or (
3653 isinstance(self.sched.layout.pipelines['gate'].
Joshua Heskethde958652015-11-10 19:19:50 +11003654 merge_failure_actions[0],
Joshua Heskethffe42062014-09-05 21:43:52 +10003655 zuul.reporter.gerrit.GerritReporter) and
Joshua Heskethb7179772014-01-30 23:30:46 +11003656 isinstance(self.sched.layout.pipelines['gate'].
Joshua Heskethde958652015-11-10 19:19:50 +11003657 merge_failure_actions[1],
Joshua Heskethffe42062014-09-05 21:43:52 +10003658 zuul.reporter.smtp.SMTPReporter)
Joshua Heskethb7179772014-01-30 23:30:46 +11003659 )
3660 )
3661
3662 def test_merge_failure_reports(self):
3663 """Check that when a change fails to merge the correct message is sent
3664 to the correct reporter"""
3665 self.config.set('zuul', 'layout_config',
3666 'tests/fixtures/layout-merge-failure.yaml')
3667 self.sched.reconfigure(self.config)
3668 self.registerJobs()
3669
3670 # Check a test failure isn't reported to SMTP
3671 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3672 A.addApproval('CRVW', 2)
3673 self.worker.addFailTest('project-test1', A)
3674 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3675 self.waitUntilSettled()
3676
3677 self.assertEqual(3, len(self.history)) # 3 jobs
3678 self.assertEqual(0, len(self.smtp_messages))
3679
3680 # Check a merge failure is reported to SMTP
3681 # B should be merged, but C will conflict with B
3682 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
3683 B.addPatchset(['conflict'])
3684 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
3685 C.addPatchset(['conflict'])
3686 B.addApproval('CRVW', 2)
3687 C.addApproval('CRVW', 2)
3688 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3689 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
3690 self.waitUntilSettled()
3691
3692 self.assertEqual(6, len(self.history)) # A and B jobs
3693 self.assertEqual(1, len(self.smtp_messages))
3694 self.assertEqual('The merge failed! For more information...',
3695 self.smtp_messages[0]['body'])
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11003696
James E. Blairf760f0e2016-02-09 08:44:52 -08003697 def test_default_merge_failure_reports(self):
3698 """Check that the default merge failure reports are correct."""
3699
3700 # A should report success, B should report merge failure.
3701 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3702 A.addPatchset(['conflict'])
3703 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
3704 B.addPatchset(['conflict'])
3705 A.addApproval('CRVW', 2)
3706 B.addApproval('CRVW', 2)
3707 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3708 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3709 self.waitUntilSettled()
3710
3711 self.assertEqual(3, len(self.history)) # A jobs
3712 self.assertEqual(A.reported, 2)
3713 self.assertEqual(B.reported, 2)
3714 self.assertEqual(A.data['status'], 'MERGED')
3715 self.assertEqual(B.data['status'], 'NEW')
3716 self.assertIn('Build succeeded', A.messages[1])
3717 self.assertIn('Merge Failed', B.messages[1])
3718 self.assertIn('automatically merged', B.messages[1])
3719 self.assertNotIn('logs.example.com', B.messages[1])
3720 self.assertNotIn('SKIPPED', B.messages[1])
3721
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11003722 def test_swift_instructions(self):
3723 "Test that the correct swift instructions are sent to the workers"
3724 self.config.set('zuul', 'layout_config',
3725 'tests/fixtures/layout-swift.yaml')
3726 self.sched.reconfigure(self.config)
3727 self.registerJobs()
3728
3729 self.worker.hold_jobs_in_build = True
3730 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3731
3732 A.addApproval('CRVW', 2)
3733 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3734 self.waitUntilSettled()
3735
3736 self.assertEqual(
3737 "https://storage.example.org/V1/AUTH_account/merge_logs/1/1/1/"
3738 "gate/test-merge/",
Joshua Hesketh76dee532014-07-03 15:39:13 +10003739 self.builds[0].parameters['SWIFT_logs_URL'][:-7])
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11003740 self.assertEqual(5,
3741 len(self.builds[0].parameters['SWIFT_logs_HMAC_BODY'].
3742 split('\n')))
3743 self.assertIn('SWIFT_logs_SIGNATURE', self.builds[0].parameters)
3744
3745 self.assertEqual(
3746 "https://storage.example.org/V1/AUTH_account/logs/1/1/1/"
3747 "gate/test-test/",
Joshua Hesketh76dee532014-07-03 15:39:13 +10003748 self.builds[1].parameters['SWIFT_logs_URL'][:-7])
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11003749 self.assertEqual(5,
3750 len(self.builds[1].parameters['SWIFT_logs_HMAC_BODY'].
3751 split('\n')))
3752 self.assertIn('SWIFT_logs_SIGNATURE', self.builds[1].parameters)
3753
3754 self.assertEqual(
3755 "https://storage.example.org/V1/AUTH_account/stash/1/1/1/"
3756 "gate/test-test/",
Joshua Hesketh76dee532014-07-03 15:39:13 +10003757 self.builds[1].parameters['SWIFT_MOSTLY_URL'][:-7])
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11003758 self.assertEqual(5,
3759 len(self.builds[1].
3760 parameters['SWIFT_MOSTLY_HMAC_BODY'].split('\n')))
3761 self.assertIn('SWIFT_MOSTLY_SIGNATURE', self.builds[1].parameters)
3762
3763 self.worker.hold_jobs_in_build = False
3764 self.worker.release()
3765 self.waitUntilSettled()
Joshua Hesketh85af4e92014-02-21 08:28:58 -08003766
3767 def test_client_get_running_jobs(self):
3768 "Test that the RPC client can get a list of running jobs"
3769 self.worker.hold_jobs_in_build = True
3770 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3771 A.addApproval('CRVW', 2)
3772 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3773 self.waitUntilSettled()
3774
3775 client = zuul.rpcclient.RPCClient('127.0.0.1',
3776 self.gearman_server.port)
3777
3778 # Wait for gearman server to send the initial workData back to zuul
3779 start = time.time()
3780 while True:
3781 if time.time() - start > 10:
3782 raise Exception("Timeout waiting for gearman server to report "
3783 + "back to the client")
3784 build = self.launcher.builds.values()[0]
3785 if build.worker.name == "My Worker":
3786 break
3787 else:
3788 time.sleep(0)
3789
3790 running_items = client.get_running_jobs()
3791
3792 self.assertEqual(1, len(running_items))
3793 running_item = running_items[0]
3794 self.assertEqual([], running_item['failing_reasons'])
3795 self.assertEqual([], running_item['items_behind'])
3796 self.assertEqual('https://hostname/1', running_item['url'])
3797 self.assertEqual(None, running_item['item_ahead'])
3798 self.assertEqual('org/project', running_item['project'])
3799 self.assertEqual(None, running_item['remaining_time'])
3800 self.assertEqual(True, running_item['active'])
3801 self.assertEqual('1,1', running_item['id'])
3802
3803 self.assertEqual(3, len(running_item['jobs']))
3804 for job in running_item['jobs']:
3805 if job['name'] == 'project-merge':
3806 self.assertEqual('project-merge', job['name'])
3807 self.assertEqual('gate', job['pipeline'])
3808 self.assertEqual(False, job['retry'])
Joshua Hesketh85af4e92014-02-21 08:28:58 -08003809 self.assertEqual('https://server/job/project-merge/0/',
3810 job['url'])
3811 self.assertEqual(7, len(job['worker']))
3812 self.assertEqual(False, job['canceled'])
3813 self.assertEqual(True, job['voting'])
3814 self.assertEqual(None, job['result'])
3815 self.assertEqual('gate', job['pipeline'])
3816 break
3817
3818 self.worker.hold_jobs_in_build = False
3819 self.worker.release()
3820 self.waitUntilSettled()
3821
3822 running_items = client.get_running_jobs()
3823 self.assertEqual(0, len(running_items))
James E. Blairbadc1ad2014-04-28 13:55:14 -07003824
3825 def test_nonvoting_pipeline(self):
3826 "Test that a nonvoting pipeline (experimental) can still report"
3827
Joshua Heskethcc017ea2014-04-30 19:55:25 +10003828 A = self.fake_gerrit.addFakeChange('org/experimental-project',
3829 'master', 'A')
James E. Blairbadc1ad2014-04-28 13:55:14 -07003830 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3831 self.waitUntilSettled()
Joshua Heskethcc017ea2014-04-30 19:55:25 +10003832 self.assertEqual(
3833 self.getJobFromHistory('experimental-project-test').result,
3834 'SUCCESS')
James E. Blairbadc1ad2014-04-28 13:55:14 -07003835 self.assertEqual(A.reported, 1)
James E. Blair5ee24252014-12-30 10:12:29 -08003836
3837 def test_crd_gate(self):
3838 "Test cross-repo dependencies"
3839 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3840 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3841 A.addApproval('CRVW', 2)
3842 B.addApproval('CRVW', 2)
3843
3844 AM2 = self.fake_gerrit.addFakeChange('org/project1', 'master', 'AM2')
3845 AM1 = self.fake_gerrit.addFakeChange('org/project1', 'master', 'AM1')
3846 AM2.setMerged()
3847 AM1.setMerged()
3848
3849 BM2 = self.fake_gerrit.addFakeChange('org/project2', 'master', 'BM2')
3850 BM1 = self.fake_gerrit.addFakeChange('org/project2', 'master', 'BM1')
3851 BM2.setMerged()
3852 BM1.setMerged()
3853
3854 # A -> AM1 -> AM2
3855 # B -> BM1 -> BM2
3856 # A Depends-On: B
3857 # M2 is here to make sure it is never queried. If it is, it
3858 # means zuul is walking down the entire history of merged
3859 # changes.
3860
3861 B.setDependsOn(BM1, 1)
3862 BM1.setDependsOn(BM2, 1)
3863
3864 A.setDependsOn(AM1, 1)
3865 AM1.setDependsOn(AM2, 1)
3866
3867 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3868 A.subject, B.data['id'])
3869
3870 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3871 self.waitUntilSettled()
3872
3873 self.assertEqual(A.data['status'], 'NEW')
3874 self.assertEqual(B.data['status'], 'NEW')
3875
Joshua Hesketh4bd7da32016-02-17 20:58:47 +11003876 for connection in self.connections.values():
3877 connection.maintainCache([])
James E. Blair5ee24252014-12-30 10:12:29 -08003878
3879 self.worker.hold_jobs_in_build = True
3880 B.addApproval('APRV', 1)
3881 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3882 self.waitUntilSettled()
3883
3884 self.worker.release('.*-merge')
3885 self.waitUntilSettled()
3886 self.worker.release('.*-merge')
3887 self.waitUntilSettled()
3888 self.worker.hold_jobs_in_build = False
3889 self.worker.release()
3890 self.waitUntilSettled()
3891
3892 self.assertEqual(AM2.queried, 0)
3893 self.assertEqual(BM2.queried, 0)
3894 self.assertEqual(A.data['status'], 'MERGED')
3895 self.assertEqual(B.data['status'], 'MERGED')
3896 self.assertEqual(A.reported, 2)
3897 self.assertEqual(B.reported, 2)
3898
James E. Blair8f78d882015-02-05 08:51:37 -08003899 self.assertEqual(self.getJobFromHistory('project1-merge').changes,
3900 '2,1 1,1')
3901
3902 def test_crd_branch(self):
3903 "Test cross-repo dependencies in multiple branches"
3904 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3905 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
K Jonathan Harker773651a2015-12-08 09:50:55 -08003906 C1 = self.fake_gerrit.addFakeChange('org/project2', 'mp', 'C1')
3907 C2 = self.fake_gerrit.addFakeChange('org/project2', 'mp', 'C2',
3908 status="ABANDONED")
3909 C1.data['id'] = B.data['id']
3910 C2.data['id'] = B.data['id']
3911
James E. Blair8f78d882015-02-05 08:51:37 -08003912 A.addApproval('CRVW', 2)
3913 B.addApproval('CRVW', 2)
K Jonathan Harker773651a2015-12-08 09:50:55 -08003914 C1.addApproval('CRVW', 2)
James E. Blair8f78d882015-02-05 08:51:37 -08003915
K Jonathan Harker773651a2015-12-08 09:50:55 -08003916 # A Depends-On: B+C1
James E. Blair8f78d882015-02-05 08:51:37 -08003917 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3918 A.subject, B.data['id'])
3919
3920 self.worker.hold_jobs_in_build = True
3921 B.addApproval('APRV', 1)
K Jonathan Harker773651a2015-12-08 09:50:55 -08003922 C1.addApproval('APRV', 1)
James E. Blair8f78d882015-02-05 08:51:37 -08003923 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3924 self.waitUntilSettled()
3925
3926 self.worker.release('.*-merge')
3927 self.waitUntilSettled()
3928 self.worker.release('.*-merge')
3929 self.waitUntilSettled()
3930 self.worker.release('.*-merge')
3931 self.waitUntilSettled()
3932 self.worker.hold_jobs_in_build = False
3933 self.worker.release()
3934 self.waitUntilSettled()
3935
3936 self.assertEqual(A.data['status'], 'MERGED')
3937 self.assertEqual(B.data['status'], 'MERGED')
K Jonathan Harker773651a2015-12-08 09:50:55 -08003938 self.assertEqual(C1.data['status'], 'MERGED')
James E. Blair8f78d882015-02-05 08:51:37 -08003939 self.assertEqual(A.reported, 2)
3940 self.assertEqual(B.reported, 2)
K Jonathan Harker773651a2015-12-08 09:50:55 -08003941 self.assertEqual(C1.reported, 2)
James E. Blair8f78d882015-02-05 08:51:37 -08003942
3943 self.assertEqual(self.getJobFromHistory('project1-merge').changes,
3944 '2,1 3,1 1,1')
3945
3946 def test_crd_multiline(self):
3947 "Test multiple depends-on lines in commit"
3948 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3949 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3950 C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
3951 A.addApproval('CRVW', 2)
3952 B.addApproval('CRVW', 2)
3953 C.addApproval('CRVW', 2)
3954
3955 # A Depends-On: B+C
3956 A.data['commitMessage'] = '%s\n\nDepends-On: %s\nDepends-On: %s\n' % (
3957 A.subject, B.data['id'], C.data['id'])
3958
3959 self.worker.hold_jobs_in_build = True
3960 B.addApproval('APRV', 1)
3961 C.addApproval('APRV', 1)
3962 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3963 self.waitUntilSettled()
3964
3965 self.worker.release('.*-merge')
3966 self.waitUntilSettled()
3967 self.worker.release('.*-merge')
3968 self.waitUntilSettled()
3969 self.worker.release('.*-merge')
3970 self.waitUntilSettled()
3971 self.worker.hold_jobs_in_build = False
3972 self.worker.release()
3973 self.waitUntilSettled()
3974
3975 self.assertEqual(A.data['status'], 'MERGED')
3976 self.assertEqual(B.data['status'], 'MERGED')
3977 self.assertEqual(C.data['status'], 'MERGED')
3978 self.assertEqual(A.reported, 2)
3979 self.assertEqual(B.reported, 2)
3980 self.assertEqual(C.reported, 2)
3981
3982 self.assertEqual(self.getJobFromHistory('project1-merge').changes,
3983 '2,1 3,1 1,1')
James E. Blair5ee24252014-12-30 10:12:29 -08003984
3985 def test_crd_unshared_gate(self):
3986 "Test cross-repo dependencies in unshared gate queues"
3987 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3988 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
3989 A.addApproval('CRVW', 2)
3990 B.addApproval('CRVW', 2)
3991
3992 # A Depends-On: B
3993 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3994 A.subject, B.data['id'])
3995
3996 # A and B do not share a queue, make sure that A is unable to
3997 # enqueue B (and therefore, A is unable to be enqueued).
3998 B.addApproval('APRV', 1)
3999 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
4000 self.waitUntilSettled()
4001
4002 self.assertEqual(A.data['status'], 'NEW')
4003 self.assertEqual(B.data['status'], 'NEW')
4004 self.assertEqual(A.reported, 0)
4005 self.assertEqual(B.reported, 0)
4006 self.assertEqual(len(self.history), 0)
4007
4008 # Enqueue and merge B alone.
4009 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
4010 self.waitUntilSettled()
4011
4012 self.assertEqual(B.data['status'], 'MERGED')
4013 self.assertEqual(B.reported, 2)
4014
4015 # Now that B is merged, A should be able to be enqueued and
4016 # merged.
4017 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
4018 self.waitUntilSettled()
4019
4020 self.assertEqual(A.data['status'], 'MERGED')
4021 self.assertEqual(A.reported, 2)
4022
James E. Blair96698e22015-04-02 07:48:21 -07004023 def test_crd_gate_reverse(self):
4024 "Test reverse cross-repo dependencies"
4025 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
4026 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
4027 A.addApproval('CRVW', 2)
4028 B.addApproval('CRVW', 2)
4029
4030 # A Depends-On: B
4031
4032 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
4033 A.subject, B.data['id'])
4034
4035 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
4036 self.waitUntilSettled()
4037
4038 self.assertEqual(A.data['status'], 'NEW')
4039 self.assertEqual(B.data['status'], 'NEW')
4040
4041 self.worker.hold_jobs_in_build = True
4042 A.addApproval('APRV', 1)
4043 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
4044 self.waitUntilSettled()
4045
4046 self.worker.release('.*-merge')
4047 self.waitUntilSettled()
4048 self.worker.release('.*-merge')
4049 self.waitUntilSettled()
4050 self.worker.hold_jobs_in_build = False
4051 self.worker.release()
4052 self.waitUntilSettled()
4053
4054 self.assertEqual(A.data['status'], 'MERGED')
4055 self.assertEqual(B.data['status'], 'MERGED')
4056 self.assertEqual(A.reported, 2)
4057 self.assertEqual(B.reported, 2)
4058
4059 self.assertEqual(self.getJobFromHistory('project1-merge').changes,
4060 '2,1 1,1')
4061
James E. Blair5ee24252014-12-30 10:12:29 -08004062 def test_crd_cycle(self):
4063 "Test cross-repo dependency cycles"
4064 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
4065 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
4066 A.addApproval('CRVW', 2)
4067 B.addApproval('CRVW', 2)
4068
4069 # A -> B -> A (via commit-depends)
4070
4071 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
4072 A.subject, B.data['id'])
4073 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
4074 B.subject, A.data['id'])
4075
4076 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
4077 self.waitUntilSettled()
4078
4079 self.assertEqual(A.reported, 0)
4080 self.assertEqual(B.reported, 0)
4081 self.assertEqual(A.data['status'], 'NEW')
4082 self.assertEqual(B.data['status'], 'NEW')
James E. Blairbfb8e042014-12-30 17:01:44 -08004083
Evgeny Antyshev0deaaad2015-08-03 20:22:56 +00004084 def test_crd_gate_unknown(self):
4085 "Test unknown projects in dependent pipeline"
4086 self.init_repo("org/unknown")
4087 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
4088 B = self.fake_gerrit.addFakeChange('org/unknown', 'master', 'B')
4089 A.addApproval('CRVW', 2)
4090 B.addApproval('CRVW', 2)
4091
4092 # A Depends-On: B
4093 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
4094 A.subject, B.data['id'])
4095
4096 B.addApproval('APRV', 1)
4097 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
4098 self.waitUntilSettled()
4099
4100 # Unknown projects cannot share a queue with any other
4101 # since they don't have common jobs with any other (they have no jobs).
4102 # Changes which depend on unknown project changes
4103 # should not be processed in dependent pipeline
4104 self.assertEqual(A.data['status'], 'NEW')
4105 self.assertEqual(B.data['status'], 'NEW')
4106 self.assertEqual(A.reported, 0)
4107 self.assertEqual(B.reported, 0)
4108 self.assertEqual(len(self.history), 0)
4109
4110 # Simulate change B being gated outside this layout
4111 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
4112 B.setMerged()
4113 self.waitUntilSettled()
4114 self.assertEqual(len(self.history), 0)
4115
4116 # Now that B is merged, A should be able to be enqueued and
4117 # merged.
4118 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
4119 self.waitUntilSettled()
4120
4121 self.assertEqual(A.data['status'], 'MERGED')
4122 self.assertEqual(A.reported, 2)
4123 self.assertEqual(B.data['status'], 'MERGED')
4124 self.assertEqual(B.reported, 0)
4125
James E. Blairbfb8e042014-12-30 17:01:44 -08004126 def test_crd_check(self):
4127 "Test cross-repo dependencies in independent pipelines"
4128
4129 self.gearman_server.hold_jobs_in_queue = True
4130 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
4131 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
4132
4133 # A Depends-On: B
4134 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
4135 A.subject, B.data['id'])
4136
4137 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
4138 self.waitUntilSettled()
4139
4140 queue = self.gearman_server.getQueue()
4141 ref = self.getParameter(queue[-1], 'ZUUL_REF')
4142 self.gearman_server.hold_jobs_in_queue = False
4143 self.gearman_server.release()
4144 self.waitUntilSettled()
4145
4146 path = os.path.join(self.git_root, "org/project1")
4147 repo = git.Repo(path)
4148 repo_messages = [c.message.strip() for c in repo.iter_commits(ref)]
4149 repo_messages.reverse()
4150 correct_messages = ['initial commit', 'A-1']
4151 self.assertEqual(repo_messages, correct_messages)
4152
4153 path = os.path.join(self.git_root, "org/project2")
4154 repo = git.Repo(path)
4155 repo_messages = [c.message.strip() for c in repo.iter_commits(ref)]
4156 repo_messages.reverse()
4157 correct_messages = ['initial commit', 'B-1']
4158 self.assertEqual(repo_messages, correct_messages)
4159
4160 self.assertEqual(A.data['status'], 'NEW')
4161 self.assertEqual(B.data['status'], 'NEW')
4162 self.assertEqual(A.reported, 1)
4163 self.assertEqual(B.reported, 0)
4164
4165 self.assertEqual(self.history[0].changes, '2,1 1,1')
4166 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 0)
James E. Blair8f78d882015-02-05 08:51:37 -08004167
James E. Blairdbfe1cd2015-02-07 11:41:19 -08004168 def test_crd_check_git_depends(self):
4169 "Test single-repo dependencies in independent pipelines"
James E. Blairb8c16472015-05-05 14:55:26 -07004170 self.gearman_server.hold_jobs_in_build = True
James E. Blairdbfe1cd2015-02-07 11:41:19 -08004171 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
4172 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
4173
4174 # Add two git-dependent changes and make sure they both report
4175 # success.
4176 B.setDependsOn(A, 1)
4177 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
4178 self.waitUntilSettled()
4179 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
4180 self.waitUntilSettled()
4181
James E. Blairb8c16472015-05-05 14:55:26 -07004182 self.orderedRelease()
4183 self.gearman_server.hold_jobs_in_build = False
James E. Blairdbfe1cd2015-02-07 11:41:19 -08004184 self.waitUntilSettled()
4185
4186 self.assertEqual(A.data['status'], 'NEW')
4187 self.assertEqual(B.data['status'], 'NEW')
4188 self.assertEqual(A.reported, 1)
4189 self.assertEqual(B.reported, 1)
4190
4191 self.assertEqual(self.history[0].changes, '1,1')
4192 self.assertEqual(self.history[-1].changes, '1,1 2,1')
4193 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 0)
4194
4195 self.assertIn('Build succeeded', A.messages[0])
4196 self.assertIn('Build succeeded', B.messages[0])
4197
4198 def test_crd_check_duplicate(self):
4199 "Test duplicate check in independent pipelines"
James E. Blair1e263032015-05-07 14:35:34 -07004200 self.worker.hold_jobs_in_build = True
James E. Blairdbfe1cd2015-02-07 11:41:19 -08004201 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
4202 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
4203 check_pipeline = self.sched.layout.pipelines['check']
4204
4205 # Add two git-dependent changes...
4206 B.setDependsOn(A, 1)
4207 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
4208 self.waitUntilSettled()
4209 self.assertEqual(len(check_pipeline.getAllItems()), 2)
4210
4211 # ...make sure the live one is not duplicated...
4212 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
4213 self.waitUntilSettled()
4214 self.assertEqual(len(check_pipeline.getAllItems()), 2)
4215
4216 # ...but the non-live one is able to be.
4217 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
4218 self.waitUntilSettled()
4219 self.assertEqual(len(check_pipeline.getAllItems()), 3)
4220
Clark Boylandd849822015-03-02 12:38:14 -08004221 # Release jobs in order to avoid races with change A jobs
4222 # finishing before change B jobs.
James E. Blaird7650852015-05-07 15:47:37 -07004223 self.orderedRelease()
James E. Blair1e263032015-05-07 14:35:34 -07004224 self.worker.hold_jobs_in_build = False
4225 self.worker.release()
James E. Blairdbfe1cd2015-02-07 11:41:19 -08004226 self.waitUntilSettled()
4227
4228 self.assertEqual(A.data['status'], 'NEW')
4229 self.assertEqual(B.data['status'], 'NEW')
4230 self.assertEqual(A.reported, 1)
4231 self.assertEqual(B.reported, 1)
4232
4233 self.assertEqual(self.history[0].changes, '1,1 2,1')
4234 self.assertEqual(self.history[1].changes, '1,1')
4235 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 0)
4236
4237 self.assertIn('Build succeeded', A.messages[0])
4238 self.assertIn('Build succeeded', B.messages[0])
4239
Evgeny Antyshev0deaaad2015-08-03 20:22:56 +00004240 def _test_crd_check_reconfiguration(self, project1, project2):
James E. Blair8f78d882015-02-05 08:51:37 -08004241 "Test cross-repo dependencies re-enqueued in independent pipelines"
4242
4243 self.gearman_server.hold_jobs_in_queue = True
Evgeny Antyshev0deaaad2015-08-03 20:22:56 +00004244 A = self.fake_gerrit.addFakeChange(project1, 'master', 'A')
4245 B = self.fake_gerrit.addFakeChange(project2, 'master', 'B')
James E. Blair8f78d882015-02-05 08:51:37 -08004246
4247 # A Depends-On: B
4248 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
4249 A.subject, B.data['id'])
4250
4251 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
4252 self.waitUntilSettled()
4253
4254 self.sched.reconfigure(self.config)
4255
4256 # Make sure the items still share a change queue, and the
4257 # first one is not live.
4258 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 1)
4259 queue = self.sched.layout.pipelines['check'].queues[0]
4260 first_item = queue.queue[0]
4261 for item in queue.queue:
4262 self.assertEqual(item.queue, first_item.queue)
4263 self.assertFalse(first_item.live)
4264 self.assertTrue(queue.queue[1].live)
4265
4266 self.gearman_server.hold_jobs_in_queue = False
4267 self.gearman_server.release()
4268 self.waitUntilSettled()
4269
4270 self.assertEqual(A.data['status'], 'NEW')
4271 self.assertEqual(B.data['status'], 'NEW')
4272 self.assertEqual(A.reported, 1)
4273 self.assertEqual(B.reported, 0)
4274
4275 self.assertEqual(self.history[0].changes, '2,1 1,1')
4276 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 0)
James E. Blair17dd6772015-02-09 14:45:18 -08004277
Evgeny Antyshev0deaaad2015-08-03 20:22:56 +00004278 def test_crd_check_reconfiguration(self):
4279 self._test_crd_check_reconfiguration('org/project1', 'org/project2')
4280
4281 def test_crd_undefined_project(self):
4282 """Test that undefined projects in dependencies are handled for
4283 independent pipelines"""
4284 # It's a hack for fake gerrit,
4285 # as it implies repo creation upon the creation of any change
4286 self.init_repo("org/unknown")
4287 self._test_crd_check_reconfiguration('org/project1', 'org/unknown')
4288
James E. Blair17dd6772015-02-09 14:45:18 -08004289 def test_crd_check_ignore_dependencies(self):
4290 "Test cross-repo dependencies can be ignored"
4291 self.config.set('zuul', 'layout_config',
4292 'tests/fixtures/layout-ignore-dependencies.yaml')
4293 self.sched.reconfigure(self.config)
4294 self.registerJobs()
4295
4296 self.gearman_server.hold_jobs_in_queue = True
4297 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
4298 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
4299 C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
4300
4301 # A Depends-On: B
4302 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
4303 A.subject, B.data['id'])
4304 # C git-depends on B
4305 C.setDependsOn(B, 1)
4306 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
4307 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
4308 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
4309 self.waitUntilSettled()
4310
4311 # Make sure none of the items share a change queue, and all
4312 # are live.
4313 check_pipeline = self.sched.layout.pipelines['check']
4314 self.assertEqual(len(check_pipeline.queues), 3)
4315 self.assertEqual(len(check_pipeline.getAllItems()), 3)
4316 for item in check_pipeline.getAllItems():
4317 self.assertTrue(item.live)
4318
4319 self.gearman_server.hold_jobs_in_queue = False
4320 self.gearman_server.release()
4321 self.waitUntilSettled()
4322
4323 self.assertEqual(A.data['status'], 'NEW')
4324 self.assertEqual(B.data['status'], 'NEW')
4325 self.assertEqual(C.data['status'], 'NEW')
4326 self.assertEqual(A.reported, 1)
4327 self.assertEqual(B.reported, 1)
4328 self.assertEqual(C.reported, 1)
4329
4330 # Each job should have tested exactly one change
4331 for job in self.history:
4332 self.assertEqual(len(job.changes.split()), 1)
James E. Blair96698e22015-04-02 07:48:21 -07004333
4334 def test_crd_check_transitive(self):
4335 "Test transitive cross-repo dependencies"
4336 # Specifically, if A -> B -> C, and C gets a new patchset and
4337 # A gets a new patchset, ensure the test of A,2 includes B,1
4338 # and C,2 (not C,1 which would indicate stale data in the
4339 # cache for B).
4340 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
4341 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
4342 C = self.fake_gerrit.addFakeChange('org/project3', 'master', 'C')
4343
4344 # A Depends-On: B
4345 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
4346 A.subject, B.data['id'])
4347
4348 # B Depends-On: C
4349 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
4350 B.subject, C.data['id'])
4351
4352 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
4353 self.waitUntilSettled()
4354 self.assertEqual(self.history[-1].changes, '3,1 2,1 1,1')
4355
4356 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
4357 self.waitUntilSettled()
4358 self.assertEqual(self.history[-1].changes, '3,1 2,1')
4359
4360 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
4361 self.waitUntilSettled()
4362 self.assertEqual(self.history[-1].changes, '3,1')
4363
4364 C.addPatchset()
4365 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(2))
4366 self.waitUntilSettled()
4367 self.assertEqual(self.history[-1].changes, '3,2')
4368
4369 A.addPatchset()
4370 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
4371 self.waitUntilSettled()
4372 self.assertEqual(self.history[-1].changes, '3,2 2,1 1,2')
Joshua Hesketh89e829d2015-02-10 16:29:45 +11004373
James E. Blaira8b90b32016-08-24 15:18:50 -07004374 def test_crd_check_unknown(self):
4375 "Test unknown projects in independent pipeline"
4376 self.init_repo("org/unknown")
4377 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
4378 B = self.fake_gerrit.addFakeChange('org/unknown', 'master', 'D')
4379 # A Depends-On: B
4380 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
4381 A.subject, B.data['id'])
4382
4383 # Make sure zuul has seen an event on B.
4384 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
4385 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
4386 self.waitUntilSettled()
4387
4388 self.assertEqual(A.data['status'], 'NEW')
4389 self.assertEqual(A.reported, 1)
4390 self.assertEqual(B.data['status'], 'NEW')
4391 self.assertEqual(B.reported, 0)
4392
James E. Blair92464a22016-04-05 10:21:26 -07004393 def test_crd_cycle_join(self):
4394 "Test an updated change creates a cycle"
4395 A = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A')
4396
4397 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
4398 self.waitUntilSettled()
4399
4400 # Create B->A
4401 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
4402 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
4403 B.subject, A.data['id'])
4404 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
4405 self.waitUntilSettled()
4406
4407 # Update A to add A->B (a cycle).
4408 A.addPatchset()
4409 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
4410 A.subject, B.data['id'])
4411 # Normally we would submit the patchset-created event for
4412 # processing here, however, we have no way of noting whether
4413 # the dependency cycle detection correctly raised an
4414 # exception, so instead, we reach into the source driver and
4415 # call the method that would ultimately be called by the event
4416 # processing.
4417
4418 source = self.sched.layout.pipelines['gate'].source
4419 with testtools.ExpectedException(
4420 Exception, "Dependency cycle detected"):
4421 source._getChange(u'1', u'2', True)
4422 self.log.debug("Got expected dependency cycle exception")
4423
4424 # Now if we update B to remove the depends-on, everything
4425 # should be okay. B; A->B
4426
4427 B.addPatchset()
4428 B.data['commitMessage'] = '%s\n' % (B.subject,)
4429 source._getChange(u'1', u'2', True)
4430 source._getChange(u'2', u'2', True)
4431
Joshua Hesketh89e829d2015-02-10 16:29:45 +11004432 def test_disable_at(self):
4433 "Test a pipeline will only report to the disabled trigger when failing"
4434
4435 self.config.set('zuul', 'layout_config',
4436 'tests/fixtures/layout-disable-at.yaml')
4437 self.sched.reconfigure(self.config)
4438
4439 self.assertEqual(3, self.sched.layout.pipelines['check'].disable_at)
4440 self.assertEqual(
4441 0, self.sched.layout.pipelines['check']._consecutive_failures)
4442 self.assertFalse(self.sched.layout.pipelines['check']._disabled)
4443
4444 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
4445 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
4446 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
4447 D = self.fake_gerrit.addFakeChange('org/project', 'master', 'D')
4448 E = self.fake_gerrit.addFakeChange('org/project', 'master', 'E')
4449 F = self.fake_gerrit.addFakeChange('org/project', 'master', 'F')
4450 G = self.fake_gerrit.addFakeChange('org/project', 'master', 'G')
4451 H = self.fake_gerrit.addFakeChange('org/project', 'master', 'H')
4452 I = self.fake_gerrit.addFakeChange('org/project', 'master', 'I')
4453 J = self.fake_gerrit.addFakeChange('org/project', 'master', 'J')
4454 K = self.fake_gerrit.addFakeChange('org/project', 'master', 'K')
4455
4456 self.worker.addFailTest('project-test1', A)
4457 self.worker.addFailTest('project-test1', B)
4458 # Let C pass, resetting the counter
4459 self.worker.addFailTest('project-test1', D)
4460 self.worker.addFailTest('project-test1', E)
4461 self.worker.addFailTest('project-test1', F)
4462 self.worker.addFailTest('project-test1', G)
4463 self.worker.addFailTest('project-test1', H)
4464 # I also passes but should only report to the disabled reporters
4465 self.worker.addFailTest('project-test1', J)
4466 self.worker.addFailTest('project-test1', K)
4467
4468 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
4469 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
4470 self.waitUntilSettled()
4471
4472 self.assertEqual(
4473 2, self.sched.layout.pipelines['check']._consecutive_failures)
4474 self.assertFalse(self.sched.layout.pipelines['check']._disabled)
4475
4476 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
4477 self.waitUntilSettled()
4478
4479 self.assertEqual(
4480 0, self.sched.layout.pipelines['check']._consecutive_failures)
4481 self.assertFalse(self.sched.layout.pipelines['check']._disabled)
4482
4483 self.fake_gerrit.addEvent(D.getPatchsetCreatedEvent(1))
4484 self.fake_gerrit.addEvent(E.getPatchsetCreatedEvent(1))
4485 self.fake_gerrit.addEvent(F.getPatchsetCreatedEvent(1))
4486 self.waitUntilSettled()
4487
4488 # We should be disabled now
4489 self.assertEqual(
4490 3, self.sched.layout.pipelines['check']._consecutive_failures)
4491 self.assertTrue(self.sched.layout.pipelines['check']._disabled)
4492
4493 # We need to wait between each of these patches to make sure the
4494 # smtp messages come back in an expected order
4495 self.fake_gerrit.addEvent(G.getPatchsetCreatedEvent(1))
4496 self.waitUntilSettled()
4497 self.fake_gerrit.addEvent(H.getPatchsetCreatedEvent(1))
4498 self.waitUntilSettled()
4499 self.fake_gerrit.addEvent(I.getPatchsetCreatedEvent(1))
4500 self.waitUntilSettled()
4501
4502 # The first 6 (ABCDEF) jobs should have reported back to gerrt thus
4503 # leaving a message on each change
4504 self.assertEqual(1, len(A.messages))
4505 self.assertIn('Build failed.', A.messages[0])
4506 self.assertEqual(1, len(B.messages))
4507 self.assertIn('Build failed.', B.messages[0])
4508 self.assertEqual(1, len(C.messages))
4509 self.assertIn('Build succeeded.', C.messages[0])
4510 self.assertEqual(1, len(D.messages))
4511 self.assertIn('Build failed.', D.messages[0])
4512 self.assertEqual(1, len(E.messages))
4513 self.assertIn('Build failed.', E.messages[0])
4514 self.assertEqual(1, len(F.messages))
4515 self.assertIn('Build failed.', F.messages[0])
4516
4517 # The last 3 (GHI) would have only reported via smtp.
4518 self.assertEqual(3, len(self.smtp_messages))
4519 self.assertEqual(0, len(G.messages))
4520 self.assertIn('Build failed.', self.smtp_messages[0]['body'])
4521 self.assertIn('/7/1/check', self.smtp_messages[0]['body'])
4522 self.assertEqual(0, len(H.messages))
4523 self.assertIn('Build failed.', self.smtp_messages[1]['body'])
4524 self.assertIn('/8/1/check', self.smtp_messages[1]['body'])
4525 self.assertEqual(0, len(I.messages))
4526 self.assertIn('Build succeeded.', self.smtp_messages[2]['body'])
4527 self.assertIn('/9/1/check', self.smtp_messages[2]['body'])
4528
4529 # Now reload the configuration (simulate a HUP) to check the pipeline
4530 # comes out of disabled
4531 self.sched.reconfigure(self.config)
4532
4533 self.assertEqual(3, self.sched.layout.pipelines['check'].disable_at)
4534 self.assertEqual(
4535 0, self.sched.layout.pipelines['check']._consecutive_failures)
4536 self.assertFalse(self.sched.layout.pipelines['check']._disabled)
4537
4538 self.fake_gerrit.addEvent(J.getPatchsetCreatedEvent(1))
4539 self.fake_gerrit.addEvent(K.getPatchsetCreatedEvent(1))
4540 self.waitUntilSettled()
4541
4542 self.assertEqual(
4543 2, self.sched.layout.pipelines['check']._consecutive_failures)
4544 self.assertFalse(self.sched.layout.pipelines['check']._disabled)
4545
4546 # J and K went back to gerrit
4547 self.assertEqual(1, len(J.messages))
4548 self.assertIn('Build failed.', J.messages[0])
4549 self.assertEqual(1, len(K.messages))
4550 self.assertIn('Build failed.', K.messages[0])
4551 # No more messages reported via smtp
4552 self.assertEqual(3, len(self.smtp_messages))
Joshua Heskethd6dbd682015-12-22 10:06:54 +11004553
4554 def test_success_pattern(self):
4555 "Ensure bad build params are ignored"
4556
4557 # Use SMTP reporter to grab the result message easier
4558 self.init_repo("org/docs")
4559 self.config.set('zuul', 'layout_config',
4560 'tests/fixtures/layout-success-pattern.yaml')
4561 self.sched.reconfigure(self.config)
4562 self.worker.hold_jobs_in_build = True
4563 self.registerJobs()
4564
4565 A = self.fake_gerrit.addFakeChange('org/docs', 'master', 'A')
4566 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
4567 self.waitUntilSettled()
4568
4569 # Grab build id
4570 self.assertEqual(len(self.builds), 1)
4571 uuid = self.builds[0].unique[:7]
4572
4573 self.worker.hold_jobs_in_build = False
4574 self.worker.release()
4575 self.waitUntilSettled()
4576
4577 self.assertEqual(len(self.smtp_messages), 1)
4578 body = self.smtp_messages[0]['body'].splitlines()
4579 self.assertEqual('Build succeeded.', body[0])
4580
4581 self.assertIn(
4582 '- docs-draft-test http://docs-draft.example.org/1/1/1/check/'
4583 'docs-draft-test/%s/publish-docs/' % uuid,
4584 body[2])
4585 self.assertIn(
4586 '- docs-draft-test2 https://server/job/docs-draft-test2/1/',
4587 body[3])
Paul Belanger71d98172016-11-08 10:56:31 -05004588
4589 def test_rerun_on_abort(self):
4590 "Test that if a worker fails to run a job, it is run again"
4591
4592 self.config.set('zuul', 'layout_config',
4593 'tests/fixtures/layout-abort-attempts.yaml')
4594 self.sched.reconfigure(self.config)
4595 self.worker.hold_jobs_in_build = True
4596 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
4597 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
4598 self.waitUntilSettled()
4599
4600 self.worker.release('.*-merge')
4601 self.waitUntilSettled()
4602
4603 self.assertEqual(len(self.builds), 2)
4604 self.builds[0].requeue = True
4605 self.worker.release('.*-test*')
4606 self.waitUntilSettled()
4607
4608 for x in range(3):
4609 self.assertEqual(len(self.builds), 1)
4610 self.builds[0].requeue = True
4611 self.worker.release('.*-test1')
4612 self.waitUntilSettled()
4613
4614 self.worker.hold_jobs_in_build = False
4615 self.worker.release()
4616 self.waitUntilSettled()
4617 self.assertEqual(len(self.history), 6)
4618 self.assertEqual(self.countJobResults(self.history, 'SUCCESS'), 2)
4619 self.assertEqual(A.reported, 1)
4620 self.assertIn('RETRY_LIMIT', A.messages[0])