blob: 8d02eeebb3f0e3fe933317b1252cdd8dc351646e [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
James E. Blair91e34592015-07-31 16:45:59 -07003080 def test_client_enqueue_change(self):
James E. Blairad28e912013-11-27 10:43:22 -08003081 "Test that the RPC client can enqueue a change"
3082 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3083 A.addApproval('CRVW', 2)
3084 A.addApproval('APRV', 1)
3085
3086 client = zuul.rpcclient.RPCClient('127.0.0.1',
3087 self.gearman_server.port)
3088 r = client.enqueue(pipeline='gate',
3089 project='org/project',
3090 trigger='gerrit',
James E. Blair36658cf2013-12-06 17:53:48 -08003091 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08003092 self.waitUntilSettled()
3093 self.assertEqual(self.getJobFromHistory('project-merge').result,
3094 'SUCCESS')
3095 self.assertEqual(self.getJobFromHistory('project-test1').result,
3096 'SUCCESS')
3097 self.assertEqual(self.getJobFromHistory('project-test2').result,
3098 'SUCCESS')
3099 self.assertEqual(A.data['status'], 'MERGED')
3100 self.assertEqual(A.reported, 2)
3101 self.assertEqual(r, True)
3102
James E. Blair91e34592015-07-31 16:45:59 -07003103 def test_client_enqueue_ref(self):
3104 "Test that the RPC client can enqueue a ref"
3105
3106 client = zuul.rpcclient.RPCClient('127.0.0.1',
3107 self.gearman_server.port)
3108 r = client.enqueue_ref(
3109 pipeline='post',
3110 project='org/project',
3111 trigger='gerrit',
3112 ref='master',
3113 oldrev='90f173846e3af9154517b88543ffbd1691f31366',
3114 newrev='d479a0bfcb34da57a31adb2a595c0cf687812543')
3115 self.waitUntilSettled()
3116 job_names = [x.name for x in self.history]
3117 self.assertEqual(len(self.history), 1)
3118 self.assertIn('project-post', job_names)
3119 self.assertEqual(r, True)
3120
James E. Blairad28e912013-11-27 10:43:22 -08003121 def test_client_enqueue_negative(self):
3122 "Test that the RPC client returns errors"
3123 client = zuul.rpcclient.RPCClient('127.0.0.1',
3124 self.gearman_server.port)
3125 with testtools.ExpectedException(zuul.rpcclient.RPCFailure,
3126 "Invalid project"):
3127 r = client.enqueue(pipeline='gate',
3128 project='project-does-not-exist',
3129 trigger='gerrit',
James E. Blair36658cf2013-12-06 17:53:48 -08003130 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08003131 client.shutdown()
3132 self.assertEqual(r, False)
3133
3134 with testtools.ExpectedException(zuul.rpcclient.RPCFailure,
3135 "Invalid pipeline"):
3136 r = client.enqueue(pipeline='pipeline-does-not-exist',
3137 project='org/project',
3138 trigger='gerrit',
James E. Blair36658cf2013-12-06 17:53:48 -08003139 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08003140 client.shutdown()
3141 self.assertEqual(r, False)
3142
3143 with testtools.ExpectedException(zuul.rpcclient.RPCFailure,
3144 "Invalid trigger"):
3145 r = client.enqueue(pipeline='gate',
3146 project='org/project',
3147 trigger='trigger-does-not-exist',
James E. Blair36658cf2013-12-06 17:53:48 -08003148 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08003149 client.shutdown()
3150 self.assertEqual(r, False)
3151
3152 with testtools.ExpectedException(zuul.rpcclient.RPCFailure,
3153 "Invalid change"):
3154 r = client.enqueue(pipeline='gate',
3155 project='org/project',
3156 trigger='gerrit',
James E. Blair36658cf2013-12-06 17:53:48 -08003157 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08003158 client.shutdown()
3159 self.assertEqual(r, False)
3160
3161 self.waitUntilSettled()
3162 self.assertEqual(len(self.history), 0)
3163 self.assertEqual(len(self.builds), 0)
James E. Blair36658cf2013-12-06 17:53:48 -08003164
3165 def test_client_promote(self):
3166 "Test that the RPC client can promote a change"
3167 self.worker.hold_jobs_in_build = True
3168 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3169 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
3170 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
3171 A.addApproval('CRVW', 2)
3172 B.addApproval('CRVW', 2)
3173 C.addApproval('CRVW', 2)
3174
3175 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3176 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3177 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
3178
3179 self.waitUntilSettled()
3180
Sean Daguef39b9ca2014-01-10 21:34:35 -05003181 items = self.sched.layout.pipelines['gate'].getAllItems()
3182 enqueue_times = {}
3183 for item in items:
3184 enqueue_times[str(item.change)] = item.enqueue_time
3185
James E. Blair36658cf2013-12-06 17:53:48 -08003186 client = zuul.rpcclient.RPCClient('127.0.0.1',
3187 self.gearman_server.port)
3188 r = client.promote(pipeline='gate',
3189 change_ids=['2,1', '3,1'])
3190
Sean Daguef39b9ca2014-01-10 21:34:35 -05003191 # ensure that enqueue times are durable
3192 items = self.sched.layout.pipelines['gate'].getAllItems()
3193 for item in items:
3194 self.assertEqual(
3195 enqueue_times[str(item.change)], item.enqueue_time)
3196
James E. Blair78acec92014-02-06 07:11:32 -08003197 self.waitUntilSettled()
James E. Blair36658cf2013-12-06 17:53:48 -08003198 self.worker.release('.*-merge')
3199 self.waitUntilSettled()
3200 self.worker.release('.*-merge')
3201 self.waitUntilSettled()
3202 self.worker.release('.*-merge')
3203 self.waitUntilSettled()
3204
3205 self.assertEqual(len(self.builds), 6)
3206 self.assertEqual(self.builds[0].name, 'project-test1')
3207 self.assertEqual(self.builds[1].name, 'project-test2')
3208 self.assertEqual(self.builds[2].name, 'project-test1')
3209 self.assertEqual(self.builds[3].name, 'project-test2')
3210 self.assertEqual(self.builds[4].name, 'project-test1')
3211 self.assertEqual(self.builds[5].name, 'project-test2')
3212
3213 self.assertTrue(self.job_has_changes(self.builds[0], B))
3214 self.assertFalse(self.job_has_changes(self.builds[0], A))
3215 self.assertFalse(self.job_has_changes(self.builds[0], C))
3216
3217 self.assertTrue(self.job_has_changes(self.builds[2], B))
3218 self.assertTrue(self.job_has_changes(self.builds[2], C))
3219 self.assertFalse(self.job_has_changes(self.builds[2], A))
3220
3221 self.assertTrue(self.job_has_changes(self.builds[4], B))
3222 self.assertTrue(self.job_has_changes(self.builds[4], C))
3223 self.assertTrue(self.job_has_changes(self.builds[4], A))
3224
3225 self.worker.release()
3226 self.waitUntilSettled()
3227
3228 self.assertEqual(A.data['status'], 'MERGED')
3229 self.assertEqual(A.reported, 2)
3230 self.assertEqual(B.data['status'], 'MERGED')
3231 self.assertEqual(B.reported, 2)
3232 self.assertEqual(C.data['status'], 'MERGED')
3233 self.assertEqual(C.reported, 2)
3234
3235 client.shutdown()
3236 self.assertEqual(r, True)
3237
3238 def test_client_promote_dependent(self):
3239 "Test that the RPC client can promote a dependent change"
3240 # C (depends on B) -> B -> A ; then promote C to get:
3241 # A -> C (depends on B) -> B
3242 self.worker.hold_jobs_in_build = True
3243 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3244 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
3245 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
3246
3247 C.setDependsOn(B, 1)
3248
3249 A.addApproval('CRVW', 2)
3250 B.addApproval('CRVW', 2)
3251 C.addApproval('CRVW', 2)
3252
3253 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3254 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3255 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
3256
3257 self.waitUntilSettled()
3258
3259 client = zuul.rpcclient.RPCClient('127.0.0.1',
3260 self.gearman_server.port)
3261 r = client.promote(pipeline='gate',
3262 change_ids=['3,1'])
3263
James E. Blair78acec92014-02-06 07:11:32 -08003264 self.waitUntilSettled()
James E. Blair36658cf2013-12-06 17:53:48 -08003265 self.worker.release('.*-merge')
3266 self.waitUntilSettled()
3267 self.worker.release('.*-merge')
3268 self.waitUntilSettled()
3269 self.worker.release('.*-merge')
3270 self.waitUntilSettled()
3271
3272 self.assertEqual(len(self.builds), 6)
3273 self.assertEqual(self.builds[0].name, 'project-test1')
3274 self.assertEqual(self.builds[1].name, 'project-test2')
3275 self.assertEqual(self.builds[2].name, 'project-test1')
3276 self.assertEqual(self.builds[3].name, 'project-test2')
3277 self.assertEqual(self.builds[4].name, 'project-test1')
3278 self.assertEqual(self.builds[5].name, 'project-test2')
3279
3280 self.assertTrue(self.job_has_changes(self.builds[0], B))
3281 self.assertFalse(self.job_has_changes(self.builds[0], A))
3282 self.assertFalse(self.job_has_changes(self.builds[0], C))
3283
3284 self.assertTrue(self.job_has_changes(self.builds[2], B))
3285 self.assertTrue(self.job_has_changes(self.builds[2], C))
3286 self.assertFalse(self.job_has_changes(self.builds[2], A))
3287
3288 self.assertTrue(self.job_has_changes(self.builds[4], B))
3289 self.assertTrue(self.job_has_changes(self.builds[4], C))
3290 self.assertTrue(self.job_has_changes(self.builds[4], A))
3291
3292 self.worker.release()
3293 self.waitUntilSettled()
3294
3295 self.assertEqual(A.data['status'], 'MERGED')
3296 self.assertEqual(A.reported, 2)
3297 self.assertEqual(B.data['status'], 'MERGED')
3298 self.assertEqual(B.reported, 2)
3299 self.assertEqual(C.data['status'], 'MERGED')
3300 self.assertEqual(C.reported, 2)
3301
3302 client.shutdown()
3303 self.assertEqual(r, True)
3304
3305 def test_client_promote_negative(self):
3306 "Test that the RPC client returns errors for promotion"
3307 self.worker.hold_jobs_in_build = True
3308 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3309 A.addApproval('CRVW', 2)
3310 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3311 self.waitUntilSettled()
3312
3313 client = zuul.rpcclient.RPCClient('127.0.0.1',
3314 self.gearman_server.port)
3315
3316 with testtools.ExpectedException(zuul.rpcclient.RPCFailure):
3317 r = client.promote(pipeline='nonexistent',
3318 change_ids=['2,1', '3,1'])
3319 client.shutdown()
3320 self.assertEqual(r, False)
3321
3322 with testtools.ExpectedException(zuul.rpcclient.RPCFailure):
3323 r = client.promote(pipeline='gate',
3324 change_ids=['4,1'])
3325 client.shutdown()
3326 self.assertEqual(r, False)
3327
3328 self.worker.hold_jobs_in_build = False
3329 self.worker.release()
3330 self.waitUntilSettled()
Clark Boylan7603a372014-01-21 11:43:20 -08003331
3332 def test_queue_rate_limiting(self):
3333 "Test that DependentPipelines are rate limited with dep across window"
3334 self.config.set('zuul', 'layout_config',
3335 'tests/fixtures/layout-rate-limit.yaml')
3336 self.sched.reconfigure(self.config)
3337 self.worker.hold_jobs_in_build = True
3338 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3339 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
3340 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
3341
3342 C.setDependsOn(B, 1)
3343 self.worker.addFailTest('project-test1', A)
3344
3345 A.addApproval('CRVW', 2)
3346 B.addApproval('CRVW', 2)
3347 C.addApproval('CRVW', 2)
3348
3349 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3350 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3351 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
3352 self.waitUntilSettled()
3353
3354 # Only A and B will have their merge jobs queued because
3355 # window is 2.
3356 self.assertEqual(len(self.builds), 2)
3357 self.assertEqual(self.builds[0].name, 'project-merge')
3358 self.assertEqual(self.builds[1].name, 'project-merge')
3359
3360 self.worker.release('.*-merge')
3361 self.waitUntilSettled()
3362 self.worker.release('.*-merge')
3363 self.waitUntilSettled()
3364
3365 # Only A and B will have their test jobs queued because
3366 # window is 2.
3367 self.assertEqual(len(self.builds), 4)
3368 self.assertEqual(self.builds[0].name, 'project-test1')
3369 self.assertEqual(self.builds[1].name, 'project-test2')
3370 self.assertEqual(self.builds[2].name, 'project-test1')
3371 self.assertEqual(self.builds[3].name, 'project-test2')
3372
3373 self.worker.release('project-.*')
3374 self.waitUntilSettled()
3375
3376 queue = self.sched.layout.pipelines['gate'].queues[0]
3377 # A failed so window is reduced by 1 to 1.
3378 self.assertEqual(queue.window, 1)
3379 self.assertEqual(queue.window_floor, 1)
3380 self.assertEqual(A.data['status'], 'NEW')
3381
3382 # Gate is reset and only B's merge job is queued because
3383 # window shrunk to 1.
3384 self.assertEqual(len(self.builds), 1)
3385 self.assertEqual(self.builds[0].name, 'project-merge')
3386
3387 self.worker.release('.*-merge')
3388 self.waitUntilSettled()
3389
3390 # Only B's test jobs are queued because window is still 1.
3391 self.assertEqual(len(self.builds), 2)
3392 self.assertEqual(self.builds[0].name, 'project-test1')
3393 self.assertEqual(self.builds[1].name, 'project-test2')
3394
3395 self.worker.release('project-.*')
3396 self.waitUntilSettled()
3397
3398 # B was successfully merged so window is increased to 2.
3399 self.assertEqual(queue.window, 2)
3400 self.assertEqual(queue.window_floor, 1)
3401 self.assertEqual(B.data['status'], 'MERGED')
3402
3403 # Only C is left and its merge job is queued.
3404 self.assertEqual(len(self.builds), 1)
3405 self.assertEqual(self.builds[0].name, 'project-merge')
3406
3407 self.worker.release('.*-merge')
3408 self.waitUntilSettled()
3409
3410 # After successful merge job the test jobs for C are queued.
3411 self.assertEqual(len(self.builds), 2)
3412 self.assertEqual(self.builds[0].name, 'project-test1')
3413 self.assertEqual(self.builds[1].name, 'project-test2')
3414
3415 self.worker.release('project-.*')
3416 self.waitUntilSettled()
3417
3418 # C successfully merged so window is bumped to 3.
3419 self.assertEqual(queue.window, 3)
3420 self.assertEqual(queue.window_floor, 1)
3421 self.assertEqual(C.data['status'], 'MERGED')
3422
3423 def test_queue_rate_limiting_dependent(self):
3424 "Test that DependentPipelines are rate limited with dep in window"
3425 self.config.set('zuul', 'layout_config',
3426 'tests/fixtures/layout-rate-limit.yaml')
3427 self.sched.reconfigure(self.config)
3428 self.worker.hold_jobs_in_build = True
3429 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3430 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
3431 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
3432
3433 B.setDependsOn(A, 1)
3434
3435 self.worker.addFailTest('project-test1', A)
3436
3437 A.addApproval('CRVW', 2)
3438 B.addApproval('CRVW', 2)
3439 C.addApproval('CRVW', 2)
3440
3441 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3442 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3443 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
3444 self.waitUntilSettled()
3445
3446 # Only A and B will have their merge jobs queued because
3447 # window is 2.
3448 self.assertEqual(len(self.builds), 2)
3449 self.assertEqual(self.builds[0].name, 'project-merge')
3450 self.assertEqual(self.builds[1].name, 'project-merge')
3451
3452 self.worker.release('.*-merge')
3453 self.waitUntilSettled()
3454 self.worker.release('.*-merge')
3455 self.waitUntilSettled()
3456
3457 # Only A and B will have their test jobs queued because
3458 # window is 2.
3459 self.assertEqual(len(self.builds), 4)
3460 self.assertEqual(self.builds[0].name, 'project-test1')
3461 self.assertEqual(self.builds[1].name, 'project-test2')
3462 self.assertEqual(self.builds[2].name, 'project-test1')
3463 self.assertEqual(self.builds[3].name, 'project-test2')
3464
3465 self.worker.release('project-.*')
3466 self.waitUntilSettled()
3467
3468 queue = self.sched.layout.pipelines['gate'].queues[0]
3469 # A failed so window is reduced by 1 to 1.
3470 self.assertEqual(queue.window, 1)
3471 self.assertEqual(queue.window_floor, 1)
3472 self.assertEqual(A.data['status'], 'NEW')
3473 self.assertEqual(B.data['status'], 'NEW')
3474
3475 # Gate is reset and only C's merge job is queued because
3476 # window shrunk to 1 and A and B were dequeued.
3477 self.assertEqual(len(self.builds), 1)
3478 self.assertEqual(self.builds[0].name, 'project-merge')
3479
3480 self.worker.release('.*-merge')
3481 self.waitUntilSettled()
3482
3483 # Only C's test jobs are queued because window is still 1.
3484 self.assertEqual(len(self.builds), 2)
3485 self.assertEqual(self.builds[0].name, 'project-test1')
3486 self.assertEqual(self.builds[1].name, 'project-test2')
3487
3488 self.worker.release('project-.*')
3489 self.waitUntilSettled()
3490
3491 # C was successfully merged so window is increased to 2.
3492 self.assertEqual(queue.window, 2)
3493 self.assertEqual(queue.window_floor, 1)
3494 self.assertEqual(C.data['status'], 'MERGED')
Joshua Heskethba8776a2014-01-12 14:35:40 +08003495
3496 def test_worker_update_metadata(self):
3497 "Test if a worker can send back metadata about itself"
3498 self.worker.hold_jobs_in_build = True
3499
3500 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3501 A.addApproval('CRVW', 2)
3502 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3503 self.waitUntilSettled()
3504
3505 self.assertEqual(len(self.launcher.builds), 1)
3506
3507 self.log.debug('Current builds:')
3508 self.log.debug(self.launcher.builds)
3509
3510 start = time.time()
3511 while True:
3512 if time.time() - start > 10:
3513 raise Exception("Timeout waiting for gearman server to report "
3514 + "back to the client")
3515 build = self.launcher.builds.values()[0]
3516 if build.worker.name == "My Worker":
3517 break
3518 else:
3519 time.sleep(0)
3520
3521 self.log.debug(build)
3522 self.assertEqual("My Worker", build.worker.name)
3523 self.assertEqual("localhost", build.worker.hostname)
3524 self.assertEqual(['127.0.0.1', '192.168.1.1'], build.worker.ips)
3525 self.assertEqual("zuul.example.org", build.worker.fqdn)
3526 self.assertEqual("FakeBuilder", build.worker.program)
3527 self.assertEqual("v1.1", build.worker.version)
3528 self.assertEqual({'something': 'else'}, build.worker.extra)
3529
3530 self.worker.hold_jobs_in_build = False
3531 self.worker.release()
3532 self.waitUntilSettled()
Joshua Hesketh3979e3e2014-03-04 11:21:10 +11003533
3534 def test_footer_message(self):
3535 "Test a pipeline's footer message is correctly added to the report."
3536 self.config.set('zuul', 'layout_config',
3537 'tests/fixtures/layout-footer-message.yaml')
3538 self.sched.reconfigure(self.config)
3539 self.registerJobs()
3540
3541 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3542 A.addApproval('CRVW', 2)
3543 self.worker.addFailTest('test1', A)
3544 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3545 self.waitUntilSettled()
3546
3547 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
3548 B.addApproval('CRVW', 2)
3549 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3550 self.waitUntilSettled()
3551
3552 self.assertEqual(2, len(self.smtp_messages))
3553
3554 failure_body = """\
3555Build failed. For information on how to proceed, see \
3556http://wiki.example.org/Test_Failures
3557
3558- test1 http://logs.example.com/1/1/gate/test1/0 : FAILURE in 0s
3559- test2 http://logs.example.com/1/1/gate/test2/1 : SUCCESS in 0s
3560
3561For CI problems and help debugging, contact ci@example.org"""
3562
3563 success_body = """\
3564Build succeeded.
3565
3566- test1 http://logs.example.com/2/1/gate/test1/2 : SUCCESS in 0s
3567- test2 http://logs.example.com/2/1/gate/test2/3 : SUCCESS in 0s
3568
3569For CI problems and help debugging, contact ci@example.org"""
3570
3571 self.assertEqual(failure_body, self.smtp_messages[0]['body'])
3572 self.assertEqual(success_body, self.smtp_messages[1]['body'])
Joshua Heskethb7179772014-01-30 23:30:46 +11003573
3574 def test_merge_failure_reporters(self):
3575 """Check that the config is set up correctly"""
3576
3577 self.config.set('zuul', 'layout_config',
3578 'tests/fixtures/layout-merge-failure.yaml')
3579 self.sched.reconfigure(self.config)
3580 self.registerJobs()
3581
3582 self.assertEqual(
Jeremy Stanley1c2c3c22015-06-15 21:23:19 +00003583 "Merge Failed.\n\nThis change or one of its cross-repo "
3584 "dependencies was unable to be automatically merged with the "
3585 "current state of its repository. Please rebase the change and "
3586 "upload a new patchset.",
Joshua Heskethb7179772014-01-30 23:30:46 +11003587 self.sched.layout.pipelines['check'].merge_failure_message)
3588 self.assertEqual(
3589 "The merge failed! For more information...",
3590 self.sched.layout.pipelines['gate'].merge_failure_message)
3591
3592 self.assertEqual(
3593 len(self.sched.layout.pipelines['check'].merge_failure_actions), 1)
3594 self.assertEqual(
3595 len(self.sched.layout.pipelines['gate'].merge_failure_actions), 2)
3596
3597 self.assertTrue(isinstance(
Joshua Heskethde958652015-11-10 19:19:50 +11003598 self.sched.layout.pipelines['check'].merge_failure_actions[0],
3599 zuul.reporter.gerrit.GerritReporter))
Joshua Heskethb7179772014-01-30 23:30:46 +11003600
3601 self.assertTrue(
3602 (
3603 isinstance(self.sched.layout.pipelines['gate'].
Joshua Heskethde958652015-11-10 19:19:50 +11003604 merge_failure_actions[0],
Joshua Heskethffe42062014-09-05 21:43:52 +10003605 zuul.reporter.smtp.SMTPReporter) and
Joshua Heskethb7179772014-01-30 23:30:46 +11003606 isinstance(self.sched.layout.pipelines['gate'].
Joshua Heskethde958652015-11-10 19:19:50 +11003607 merge_failure_actions[1],
Joshua Heskethffe42062014-09-05 21:43:52 +10003608 zuul.reporter.gerrit.GerritReporter)
Joshua Heskethb7179772014-01-30 23:30:46 +11003609 ) or (
3610 isinstance(self.sched.layout.pipelines['gate'].
Joshua Heskethde958652015-11-10 19:19:50 +11003611 merge_failure_actions[0],
Joshua Heskethffe42062014-09-05 21:43:52 +10003612 zuul.reporter.gerrit.GerritReporter) and
Joshua Heskethb7179772014-01-30 23:30:46 +11003613 isinstance(self.sched.layout.pipelines['gate'].
Joshua Heskethde958652015-11-10 19:19:50 +11003614 merge_failure_actions[1],
Joshua Heskethffe42062014-09-05 21:43:52 +10003615 zuul.reporter.smtp.SMTPReporter)
Joshua Heskethb7179772014-01-30 23:30:46 +11003616 )
3617 )
3618
3619 def test_merge_failure_reports(self):
3620 """Check that when a change fails to merge the correct message is sent
3621 to the correct reporter"""
3622 self.config.set('zuul', 'layout_config',
3623 'tests/fixtures/layout-merge-failure.yaml')
3624 self.sched.reconfigure(self.config)
3625 self.registerJobs()
3626
3627 # Check a test failure isn't reported to SMTP
3628 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3629 A.addApproval('CRVW', 2)
3630 self.worker.addFailTest('project-test1', A)
3631 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3632 self.waitUntilSettled()
3633
3634 self.assertEqual(3, len(self.history)) # 3 jobs
3635 self.assertEqual(0, len(self.smtp_messages))
3636
3637 # Check a merge failure is reported to SMTP
3638 # B should be merged, but C will conflict with B
3639 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
3640 B.addPatchset(['conflict'])
3641 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
3642 C.addPatchset(['conflict'])
3643 B.addApproval('CRVW', 2)
3644 C.addApproval('CRVW', 2)
3645 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3646 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
3647 self.waitUntilSettled()
3648
3649 self.assertEqual(6, len(self.history)) # A and B jobs
3650 self.assertEqual(1, len(self.smtp_messages))
3651 self.assertEqual('The merge failed! For more information...',
3652 self.smtp_messages[0]['body'])
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11003653
James E. Blairf760f0e2016-02-09 08:44:52 -08003654 def test_default_merge_failure_reports(self):
3655 """Check that the default merge failure reports are correct."""
3656
3657 # A should report success, B should report merge failure.
3658 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3659 A.addPatchset(['conflict'])
3660 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
3661 B.addPatchset(['conflict'])
3662 A.addApproval('CRVW', 2)
3663 B.addApproval('CRVW', 2)
3664 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3665 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3666 self.waitUntilSettled()
3667
3668 self.assertEqual(3, len(self.history)) # A jobs
3669 self.assertEqual(A.reported, 2)
3670 self.assertEqual(B.reported, 2)
3671 self.assertEqual(A.data['status'], 'MERGED')
3672 self.assertEqual(B.data['status'], 'NEW')
3673 self.assertIn('Build succeeded', A.messages[1])
3674 self.assertIn('Merge Failed', B.messages[1])
3675 self.assertIn('automatically merged', B.messages[1])
3676 self.assertNotIn('logs.example.com', B.messages[1])
3677 self.assertNotIn('SKIPPED', B.messages[1])
3678
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11003679 def test_swift_instructions(self):
3680 "Test that the correct swift instructions are sent to the workers"
3681 self.config.set('zuul', 'layout_config',
3682 'tests/fixtures/layout-swift.yaml')
3683 self.sched.reconfigure(self.config)
3684 self.registerJobs()
3685
3686 self.worker.hold_jobs_in_build = True
3687 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3688
3689 A.addApproval('CRVW', 2)
3690 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3691 self.waitUntilSettled()
3692
3693 self.assertEqual(
3694 "https://storage.example.org/V1/AUTH_account/merge_logs/1/1/1/"
3695 "gate/test-merge/",
Joshua Hesketh76dee532014-07-03 15:39:13 +10003696 self.builds[0].parameters['SWIFT_logs_URL'][:-7])
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11003697 self.assertEqual(5,
3698 len(self.builds[0].parameters['SWIFT_logs_HMAC_BODY'].
3699 split('\n')))
3700 self.assertIn('SWIFT_logs_SIGNATURE', self.builds[0].parameters)
3701
3702 self.assertEqual(
3703 "https://storage.example.org/V1/AUTH_account/logs/1/1/1/"
3704 "gate/test-test/",
Joshua Hesketh76dee532014-07-03 15:39:13 +10003705 self.builds[1].parameters['SWIFT_logs_URL'][:-7])
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11003706 self.assertEqual(5,
3707 len(self.builds[1].parameters['SWIFT_logs_HMAC_BODY'].
3708 split('\n')))
3709 self.assertIn('SWIFT_logs_SIGNATURE', self.builds[1].parameters)
3710
3711 self.assertEqual(
3712 "https://storage.example.org/V1/AUTH_account/stash/1/1/1/"
3713 "gate/test-test/",
Joshua Hesketh76dee532014-07-03 15:39:13 +10003714 self.builds[1].parameters['SWIFT_MOSTLY_URL'][:-7])
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11003715 self.assertEqual(5,
3716 len(self.builds[1].
3717 parameters['SWIFT_MOSTLY_HMAC_BODY'].split('\n')))
3718 self.assertIn('SWIFT_MOSTLY_SIGNATURE', self.builds[1].parameters)
3719
3720 self.worker.hold_jobs_in_build = False
3721 self.worker.release()
3722 self.waitUntilSettled()
Joshua Hesketh85af4e92014-02-21 08:28:58 -08003723
3724 def test_client_get_running_jobs(self):
3725 "Test that the RPC client can get a list of running jobs"
3726 self.worker.hold_jobs_in_build = True
3727 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3728 A.addApproval('CRVW', 2)
3729 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3730 self.waitUntilSettled()
3731
3732 client = zuul.rpcclient.RPCClient('127.0.0.1',
3733 self.gearman_server.port)
3734
3735 # Wait for gearman server to send the initial workData back to zuul
3736 start = time.time()
3737 while True:
3738 if time.time() - start > 10:
3739 raise Exception("Timeout waiting for gearman server to report "
3740 + "back to the client")
3741 build = self.launcher.builds.values()[0]
3742 if build.worker.name == "My Worker":
3743 break
3744 else:
3745 time.sleep(0)
3746
3747 running_items = client.get_running_jobs()
3748
3749 self.assertEqual(1, len(running_items))
3750 running_item = running_items[0]
3751 self.assertEqual([], running_item['failing_reasons'])
3752 self.assertEqual([], running_item['items_behind'])
3753 self.assertEqual('https://hostname/1', running_item['url'])
3754 self.assertEqual(None, running_item['item_ahead'])
3755 self.assertEqual('org/project', running_item['project'])
3756 self.assertEqual(None, running_item['remaining_time'])
3757 self.assertEqual(True, running_item['active'])
3758 self.assertEqual('1,1', running_item['id'])
3759
3760 self.assertEqual(3, len(running_item['jobs']))
3761 for job in running_item['jobs']:
3762 if job['name'] == 'project-merge':
3763 self.assertEqual('project-merge', job['name'])
3764 self.assertEqual('gate', job['pipeline'])
3765 self.assertEqual(False, job['retry'])
Joshua Hesketh85af4e92014-02-21 08:28:58 -08003766 self.assertEqual('https://server/job/project-merge/0/',
3767 job['url'])
3768 self.assertEqual(7, len(job['worker']))
3769 self.assertEqual(False, job['canceled'])
3770 self.assertEqual(True, job['voting'])
3771 self.assertEqual(None, job['result'])
3772 self.assertEqual('gate', job['pipeline'])
3773 break
3774
3775 self.worker.hold_jobs_in_build = False
3776 self.worker.release()
3777 self.waitUntilSettled()
3778
3779 running_items = client.get_running_jobs()
3780 self.assertEqual(0, len(running_items))
James E. Blairbadc1ad2014-04-28 13:55:14 -07003781
3782 def test_nonvoting_pipeline(self):
3783 "Test that a nonvoting pipeline (experimental) can still report"
3784
Joshua Heskethcc017ea2014-04-30 19:55:25 +10003785 A = self.fake_gerrit.addFakeChange('org/experimental-project',
3786 'master', 'A')
James E. Blairbadc1ad2014-04-28 13:55:14 -07003787 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3788 self.waitUntilSettled()
Joshua Heskethcc017ea2014-04-30 19:55:25 +10003789 self.assertEqual(
3790 self.getJobFromHistory('experimental-project-test').result,
3791 'SUCCESS')
James E. Blairbadc1ad2014-04-28 13:55:14 -07003792 self.assertEqual(A.reported, 1)
James E. Blair5ee24252014-12-30 10:12:29 -08003793
3794 def test_crd_gate(self):
3795 "Test cross-repo dependencies"
3796 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3797 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3798 A.addApproval('CRVW', 2)
3799 B.addApproval('CRVW', 2)
3800
3801 AM2 = self.fake_gerrit.addFakeChange('org/project1', 'master', 'AM2')
3802 AM1 = self.fake_gerrit.addFakeChange('org/project1', 'master', 'AM1')
3803 AM2.setMerged()
3804 AM1.setMerged()
3805
3806 BM2 = self.fake_gerrit.addFakeChange('org/project2', 'master', 'BM2')
3807 BM1 = self.fake_gerrit.addFakeChange('org/project2', 'master', 'BM1')
3808 BM2.setMerged()
3809 BM1.setMerged()
3810
3811 # A -> AM1 -> AM2
3812 # B -> BM1 -> BM2
3813 # A Depends-On: B
3814 # M2 is here to make sure it is never queried. If it is, it
3815 # means zuul is walking down the entire history of merged
3816 # changes.
3817
3818 B.setDependsOn(BM1, 1)
3819 BM1.setDependsOn(BM2, 1)
3820
3821 A.setDependsOn(AM1, 1)
3822 AM1.setDependsOn(AM2, 1)
3823
3824 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3825 A.subject, B.data['id'])
3826
3827 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3828 self.waitUntilSettled()
3829
3830 self.assertEqual(A.data['status'], 'NEW')
3831 self.assertEqual(B.data['status'], 'NEW')
3832
Joshua Hesketh4bd7da32016-02-17 20:58:47 +11003833 for connection in self.connections.values():
3834 connection.maintainCache([])
James E. Blair5ee24252014-12-30 10:12:29 -08003835
3836 self.worker.hold_jobs_in_build = True
3837 B.addApproval('APRV', 1)
3838 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3839 self.waitUntilSettled()
3840
3841 self.worker.release('.*-merge')
3842 self.waitUntilSettled()
3843 self.worker.release('.*-merge')
3844 self.waitUntilSettled()
3845 self.worker.hold_jobs_in_build = False
3846 self.worker.release()
3847 self.waitUntilSettled()
3848
3849 self.assertEqual(AM2.queried, 0)
3850 self.assertEqual(BM2.queried, 0)
3851 self.assertEqual(A.data['status'], 'MERGED')
3852 self.assertEqual(B.data['status'], 'MERGED')
3853 self.assertEqual(A.reported, 2)
3854 self.assertEqual(B.reported, 2)
3855
James E. Blair8f78d882015-02-05 08:51:37 -08003856 self.assertEqual(self.getJobFromHistory('project1-merge').changes,
3857 '2,1 1,1')
3858
3859 def test_crd_branch(self):
3860 "Test cross-repo dependencies in multiple branches"
3861 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3862 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3863 C = self.fake_gerrit.addFakeChange('org/project2', 'mp', 'C')
3864 C.data['id'] = B.data['id']
3865 A.addApproval('CRVW', 2)
3866 B.addApproval('CRVW', 2)
3867 C.addApproval('CRVW', 2)
3868
3869 # A Depends-On: B+C
3870 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3871 A.subject, B.data['id'])
3872
3873 self.worker.hold_jobs_in_build = True
3874 B.addApproval('APRV', 1)
3875 C.addApproval('APRV', 1)
3876 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3877 self.waitUntilSettled()
3878
3879 self.worker.release('.*-merge')
3880 self.waitUntilSettled()
3881 self.worker.release('.*-merge')
3882 self.waitUntilSettled()
3883 self.worker.release('.*-merge')
3884 self.waitUntilSettled()
3885 self.worker.hold_jobs_in_build = False
3886 self.worker.release()
3887 self.waitUntilSettled()
3888
3889 self.assertEqual(A.data['status'], 'MERGED')
3890 self.assertEqual(B.data['status'], 'MERGED')
3891 self.assertEqual(C.data['status'], 'MERGED')
3892 self.assertEqual(A.reported, 2)
3893 self.assertEqual(B.reported, 2)
3894 self.assertEqual(C.reported, 2)
3895
3896 self.assertEqual(self.getJobFromHistory('project1-merge').changes,
3897 '2,1 3,1 1,1')
3898
3899 def test_crd_multiline(self):
3900 "Test multiple depends-on lines in commit"
3901 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3902 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3903 C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
3904 A.addApproval('CRVW', 2)
3905 B.addApproval('CRVW', 2)
3906 C.addApproval('CRVW', 2)
3907
3908 # A Depends-On: B+C
3909 A.data['commitMessage'] = '%s\n\nDepends-On: %s\nDepends-On: %s\n' % (
3910 A.subject, B.data['id'], C.data['id'])
3911
3912 self.worker.hold_jobs_in_build = True
3913 B.addApproval('APRV', 1)
3914 C.addApproval('APRV', 1)
3915 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3916 self.waitUntilSettled()
3917
3918 self.worker.release('.*-merge')
3919 self.waitUntilSettled()
3920 self.worker.release('.*-merge')
3921 self.waitUntilSettled()
3922 self.worker.release('.*-merge')
3923 self.waitUntilSettled()
3924 self.worker.hold_jobs_in_build = False
3925 self.worker.release()
3926 self.waitUntilSettled()
3927
3928 self.assertEqual(A.data['status'], 'MERGED')
3929 self.assertEqual(B.data['status'], 'MERGED')
3930 self.assertEqual(C.data['status'], 'MERGED')
3931 self.assertEqual(A.reported, 2)
3932 self.assertEqual(B.reported, 2)
3933 self.assertEqual(C.reported, 2)
3934
3935 self.assertEqual(self.getJobFromHistory('project1-merge').changes,
3936 '2,1 3,1 1,1')
James E. Blair5ee24252014-12-30 10:12:29 -08003937
3938 def test_crd_unshared_gate(self):
3939 "Test cross-repo dependencies in unshared gate queues"
3940 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3941 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
3942 A.addApproval('CRVW', 2)
3943 B.addApproval('CRVW', 2)
3944
3945 # A Depends-On: B
3946 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3947 A.subject, B.data['id'])
3948
3949 # A and B do not share a queue, make sure that A is unable to
3950 # enqueue B (and therefore, A is unable to be enqueued).
3951 B.addApproval('APRV', 1)
3952 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3953 self.waitUntilSettled()
3954
3955 self.assertEqual(A.data['status'], 'NEW')
3956 self.assertEqual(B.data['status'], 'NEW')
3957 self.assertEqual(A.reported, 0)
3958 self.assertEqual(B.reported, 0)
3959 self.assertEqual(len(self.history), 0)
3960
3961 # Enqueue and merge B alone.
3962 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3963 self.waitUntilSettled()
3964
3965 self.assertEqual(B.data['status'], 'MERGED')
3966 self.assertEqual(B.reported, 2)
3967
3968 # Now that B is merged, A should be able to be enqueued and
3969 # merged.
3970 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3971 self.waitUntilSettled()
3972
3973 self.assertEqual(A.data['status'], 'MERGED')
3974 self.assertEqual(A.reported, 2)
3975
James E. Blair96698e22015-04-02 07:48:21 -07003976 def test_crd_gate_reverse(self):
3977 "Test reverse cross-repo dependencies"
3978 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3979 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3980 A.addApproval('CRVW', 2)
3981 B.addApproval('CRVW', 2)
3982
3983 # A Depends-On: B
3984
3985 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3986 A.subject, B.data['id'])
3987
3988 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3989 self.waitUntilSettled()
3990
3991 self.assertEqual(A.data['status'], 'NEW')
3992 self.assertEqual(B.data['status'], 'NEW')
3993
3994 self.worker.hold_jobs_in_build = True
3995 A.addApproval('APRV', 1)
3996 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3997 self.waitUntilSettled()
3998
3999 self.worker.release('.*-merge')
4000 self.waitUntilSettled()
4001 self.worker.release('.*-merge')
4002 self.waitUntilSettled()
4003 self.worker.hold_jobs_in_build = False
4004 self.worker.release()
4005 self.waitUntilSettled()
4006
4007 self.assertEqual(A.data['status'], 'MERGED')
4008 self.assertEqual(B.data['status'], 'MERGED')
4009 self.assertEqual(A.reported, 2)
4010 self.assertEqual(B.reported, 2)
4011
4012 self.assertEqual(self.getJobFromHistory('project1-merge').changes,
4013 '2,1 1,1')
4014
James E. Blair5ee24252014-12-30 10:12:29 -08004015 def test_crd_cycle(self):
4016 "Test cross-repo dependency cycles"
4017 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
4018 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
4019 A.addApproval('CRVW', 2)
4020 B.addApproval('CRVW', 2)
4021
4022 # A -> B -> A (via commit-depends)
4023
4024 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
4025 A.subject, B.data['id'])
4026 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
4027 B.subject, A.data['id'])
4028
4029 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
4030 self.waitUntilSettled()
4031
4032 self.assertEqual(A.reported, 0)
4033 self.assertEqual(B.reported, 0)
4034 self.assertEqual(A.data['status'], 'NEW')
4035 self.assertEqual(B.data['status'], 'NEW')
James E. Blairbfb8e042014-12-30 17:01:44 -08004036
Evgeny Antyshev0deaaad2015-08-03 20:22:56 +00004037 def test_crd_gate_unknown(self):
4038 "Test unknown projects in dependent pipeline"
4039 self.init_repo("org/unknown")
4040 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
4041 B = self.fake_gerrit.addFakeChange('org/unknown', 'master', 'B')
4042 A.addApproval('CRVW', 2)
4043 B.addApproval('CRVW', 2)
4044
4045 # A Depends-On: B
4046 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
4047 A.subject, B.data['id'])
4048
4049 B.addApproval('APRV', 1)
4050 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
4051 self.waitUntilSettled()
4052
4053 # Unknown projects cannot share a queue with any other
4054 # since they don't have common jobs with any other (they have no jobs).
4055 # Changes which depend on unknown project changes
4056 # should not be processed in dependent pipeline
4057 self.assertEqual(A.data['status'], 'NEW')
4058 self.assertEqual(B.data['status'], 'NEW')
4059 self.assertEqual(A.reported, 0)
4060 self.assertEqual(B.reported, 0)
4061 self.assertEqual(len(self.history), 0)
4062
4063 # Simulate change B being gated outside this layout
4064 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
4065 B.setMerged()
4066 self.waitUntilSettled()
4067 self.assertEqual(len(self.history), 0)
4068
4069 # Now that B is merged, A should be able to be enqueued and
4070 # merged.
4071 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
4072 self.waitUntilSettled()
4073
4074 self.assertEqual(A.data['status'], 'MERGED')
4075 self.assertEqual(A.reported, 2)
4076 self.assertEqual(B.data['status'], 'MERGED')
4077 self.assertEqual(B.reported, 0)
4078
James E. Blairbfb8e042014-12-30 17:01:44 -08004079 def test_crd_check(self):
4080 "Test cross-repo dependencies in independent pipelines"
4081
4082 self.gearman_server.hold_jobs_in_queue = True
4083 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
4084 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
4085
4086 # A Depends-On: B
4087 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
4088 A.subject, B.data['id'])
4089
4090 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
4091 self.waitUntilSettled()
4092
4093 queue = self.gearman_server.getQueue()
4094 ref = self.getParameter(queue[-1], 'ZUUL_REF')
4095 self.gearman_server.hold_jobs_in_queue = False
4096 self.gearman_server.release()
4097 self.waitUntilSettled()
4098
4099 path = os.path.join(self.git_root, "org/project1")
4100 repo = git.Repo(path)
4101 repo_messages = [c.message.strip() for c in repo.iter_commits(ref)]
4102 repo_messages.reverse()
4103 correct_messages = ['initial commit', 'A-1']
4104 self.assertEqual(repo_messages, correct_messages)
4105
4106 path = os.path.join(self.git_root, "org/project2")
4107 repo = git.Repo(path)
4108 repo_messages = [c.message.strip() for c in repo.iter_commits(ref)]
4109 repo_messages.reverse()
4110 correct_messages = ['initial commit', 'B-1']
4111 self.assertEqual(repo_messages, correct_messages)
4112
4113 self.assertEqual(A.data['status'], 'NEW')
4114 self.assertEqual(B.data['status'], 'NEW')
4115 self.assertEqual(A.reported, 1)
4116 self.assertEqual(B.reported, 0)
4117
4118 self.assertEqual(self.history[0].changes, '2,1 1,1')
4119 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 0)
James E. Blair8f78d882015-02-05 08:51:37 -08004120
James E. Blairdbfe1cd2015-02-07 11:41:19 -08004121 def test_crd_check_git_depends(self):
4122 "Test single-repo dependencies in independent pipelines"
James E. Blairb8c16472015-05-05 14:55:26 -07004123 self.gearman_server.hold_jobs_in_build = True
James E. Blairdbfe1cd2015-02-07 11:41:19 -08004124 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
4125 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
4126
4127 # Add two git-dependent changes and make sure they both report
4128 # success.
4129 B.setDependsOn(A, 1)
4130 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
4131 self.waitUntilSettled()
4132 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
4133 self.waitUntilSettled()
4134
James E. Blairb8c16472015-05-05 14:55:26 -07004135 self.orderedRelease()
4136 self.gearman_server.hold_jobs_in_build = False
James E. Blairdbfe1cd2015-02-07 11:41:19 -08004137 self.waitUntilSettled()
4138
4139 self.assertEqual(A.data['status'], 'NEW')
4140 self.assertEqual(B.data['status'], 'NEW')
4141 self.assertEqual(A.reported, 1)
4142 self.assertEqual(B.reported, 1)
4143
4144 self.assertEqual(self.history[0].changes, '1,1')
4145 self.assertEqual(self.history[-1].changes, '1,1 2,1')
4146 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 0)
4147
4148 self.assertIn('Build succeeded', A.messages[0])
4149 self.assertIn('Build succeeded', B.messages[0])
4150
4151 def test_crd_check_duplicate(self):
4152 "Test duplicate check in independent pipelines"
James E. Blair1e263032015-05-07 14:35:34 -07004153 self.worker.hold_jobs_in_build = True
James E. Blairdbfe1cd2015-02-07 11:41:19 -08004154 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
4155 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
4156 check_pipeline = self.sched.layout.pipelines['check']
4157
4158 # Add two git-dependent changes...
4159 B.setDependsOn(A, 1)
4160 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
4161 self.waitUntilSettled()
4162 self.assertEqual(len(check_pipeline.getAllItems()), 2)
4163
4164 # ...make sure the live one is not duplicated...
4165 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
4166 self.waitUntilSettled()
4167 self.assertEqual(len(check_pipeline.getAllItems()), 2)
4168
4169 # ...but the non-live one is able to be.
4170 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
4171 self.waitUntilSettled()
4172 self.assertEqual(len(check_pipeline.getAllItems()), 3)
4173
Clark Boylandd849822015-03-02 12:38:14 -08004174 # Release jobs in order to avoid races with change A jobs
4175 # finishing before change B jobs.
James E. Blaird7650852015-05-07 15:47:37 -07004176 self.orderedRelease()
James E. Blair1e263032015-05-07 14:35:34 -07004177 self.worker.hold_jobs_in_build = False
4178 self.worker.release()
James E. Blairdbfe1cd2015-02-07 11:41:19 -08004179 self.waitUntilSettled()
4180
4181 self.assertEqual(A.data['status'], 'NEW')
4182 self.assertEqual(B.data['status'], 'NEW')
4183 self.assertEqual(A.reported, 1)
4184 self.assertEqual(B.reported, 1)
4185
4186 self.assertEqual(self.history[0].changes, '1,1 2,1')
4187 self.assertEqual(self.history[1].changes, '1,1')
4188 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 0)
4189
4190 self.assertIn('Build succeeded', A.messages[0])
4191 self.assertIn('Build succeeded', B.messages[0])
4192
Evgeny Antyshev0deaaad2015-08-03 20:22:56 +00004193 def _test_crd_check_reconfiguration(self, project1, project2):
James E. Blair8f78d882015-02-05 08:51:37 -08004194 "Test cross-repo dependencies re-enqueued in independent pipelines"
4195
4196 self.gearman_server.hold_jobs_in_queue = True
Evgeny Antyshev0deaaad2015-08-03 20:22:56 +00004197 A = self.fake_gerrit.addFakeChange(project1, 'master', 'A')
4198 B = self.fake_gerrit.addFakeChange(project2, 'master', 'B')
James E. Blair8f78d882015-02-05 08:51:37 -08004199
4200 # A Depends-On: B
4201 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
4202 A.subject, B.data['id'])
4203
4204 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
4205 self.waitUntilSettled()
4206
4207 self.sched.reconfigure(self.config)
4208
4209 # Make sure the items still share a change queue, and the
4210 # first one is not live.
4211 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 1)
4212 queue = self.sched.layout.pipelines['check'].queues[0]
4213 first_item = queue.queue[0]
4214 for item in queue.queue:
4215 self.assertEqual(item.queue, first_item.queue)
4216 self.assertFalse(first_item.live)
4217 self.assertTrue(queue.queue[1].live)
4218
4219 self.gearman_server.hold_jobs_in_queue = False
4220 self.gearman_server.release()
4221 self.waitUntilSettled()
4222
4223 self.assertEqual(A.data['status'], 'NEW')
4224 self.assertEqual(B.data['status'], 'NEW')
4225 self.assertEqual(A.reported, 1)
4226 self.assertEqual(B.reported, 0)
4227
4228 self.assertEqual(self.history[0].changes, '2,1 1,1')
4229 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 0)
James E. Blair17dd6772015-02-09 14:45:18 -08004230
Evgeny Antyshev0deaaad2015-08-03 20:22:56 +00004231 def test_crd_check_reconfiguration(self):
4232 self._test_crd_check_reconfiguration('org/project1', 'org/project2')
4233
4234 def test_crd_undefined_project(self):
4235 """Test that undefined projects in dependencies are handled for
4236 independent pipelines"""
4237 # It's a hack for fake gerrit,
4238 # as it implies repo creation upon the creation of any change
4239 self.init_repo("org/unknown")
4240 self._test_crd_check_reconfiguration('org/project1', 'org/unknown')
4241
James E. Blair17dd6772015-02-09 14:45:18 -08004242 def test_crd_check_ignore_dependencies(self):
4243 "Test cross-repo dependencies can be ignored"
4244 self.config.set('zuul', 'layout_config',
4245 'tests/fixtures/layout-ignore-dependencies.yaml')
4246 self.sched.reconfigure(self.config)
4247 self.registerJobs()
4248
4249 self.gearman_server.hold_jobs_in_queue = True
4250 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
4251 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
4252 C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
4253
4254 # A Depends-On: B
4255 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
4256 A.subject, B.data['id'])
4257 # C git-depends on B
4258 C.setDependsOn(B, 1)
4259 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
4260 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
4261 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
4262 self.waitUntilSettled()
4263
4264 # Make sure none of the items share a change queue, and all
4265 # are live.
4266 check_pipeline = self.sched.layout.pipelines['check']
4267 self.assertEqual(len(check_pipeline.queues), 3)
4268 self.assertEqual(len(check_pipeline.getAllItems()), 3)
4269 for item in check_pipeline.getAllItems():
4270 self.assertTrue(item.live)
4271
4272 self.gearman_server.hold_jobs_in_queue = False
4273 self.gearman_server.release()
4274 self.waitUntilSettled()
4275
4276 self.assertEqual(A.data['status'], 'NEW')
4277 self.assertEqual(B.data['status'], 'NEW')
4278 self.assertEqual(C.data['status'], 'NEW')
4279 self.assertEqual(A.reported, 1)
4280 self.assertEqual(B.reported, 1)
4281 self.assertEqual(C.reported, 1)
4282
4283 # Each job should have tested exactly one change
4284 for job in self.history:
4285 self.assertEqual(len(job.changes.split()), 1)
James E. Blair96698e22015-04-02 07:48:21 -07004286
4287 def test_crd_check_transitive(self):
4288 "Test transitive cross-repo dependencies"
4289 # Specifically, if A -> B -> C, and C gets a new patchset and
4290 # A gets a new patchset, ensure the test of A,2 includes B,1
4291 # and C,2 (not C,1 which would indicate stale data in the
4292 # cache for B).
4293 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
4294 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
4295 C = self.fake_gerrit.addFakeChange('org/project3', 'master', 'C')
4296
4297 # A Depends-On: B
4298 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
4299 A.subject, B.data['id'])
4300
4301 # B Depends-On: C
4302 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
4303 B.subject, C.data['id'])
4304
4305 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
4306 self.waitUntilSettled()
4307 self.assertEqual(self.history[-1].changes, '3,1 2,1 1,1')
4308
4309 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
4310 self.waitUntilSettled()
4311 self.assertEqual(self.history[-1].changes, '3,1 2,1')
4312
4313 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
4314 self.waitUntilSettled()
4315 self.assertEqual(self.history[-1].changes, '3,1')
4316
4317 C.addPatchset()
4318 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(2))
4319 self.waitUntilSettled()
4320 self.assertEqual(self.history[-1].changes, '3,2')
4321
4322 A.addPatchset()
4323 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
4324 self.waitUntilSettled()
4325 self.assertEqual(self.history[-1].changes, '3,2 2,1 1,2')
Joshua Hesketh89e829d2015-02-10 16:29:45 +11004326
James E. Blaira8b90b32016-08-24 15:18:50 -07004327 def test_crd_check_unknown(self):
4328 "Test unknown projects in independent pipeline"
4329 self.init_repo("org/unknown")
4330 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
4331 B = self.fake_gerrit.addFakeChange('org/unknown', 'master', 'D')
4332 # A Depends-On: B
4333 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
4334 A.subject, B.data['id'])
4335
4336 # Make sure zuul has seen an event on B.
4337 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
4338 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
4339 self.waitUntilSettled()
4340
4341 self.assertEqual(A.data['status'], 'NEW')
4342 self.assertEqual(A.reported, 1)
4343 self.assertEqual(B.data['status'], 'NEW')
4344 self.assertEqual(B.reported, 0)
4345
James E. Blair92464a22016-04-05 10:21:26 -07004346 def test_crd_cycle_join(self):
4347 "Test an updated change creates a cycle"
4348 A = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A')
4349
4350 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
4351 self.waitUntilSettled()
4352
4353 # Create B->A
4354 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
4355 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
4356 B.subject, A.data['id'])
4357 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
4358 self.waitUntilSettled()
4359
4360 # Update A to add A->B (a cycle).
4361 A.addPatchset()
4362 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
4363 A.subject, B.data['id'])
4364 # Normally we would submit the patchset-created event for
4365 # processing here, however, we have no way of noting whether
4366 # the dependency cycle detection correctly raised an
4367 # exception, so instead, we reach into the source driver and
4368 # call the method that would ultimately be called by the event
4369 # processing.
4370
4371 source = self.sched.layout.pipelines['gate'].source
4372 with testtools.ExpectedException(
4373 Exception, "Dependency cycle detected"):
4374 source._getChange(u'1', u'2', True)
4375 self.log.debug("Got expected dependency cycle exception")
4376
4377 # Now if we update B to remove the depends-on, everything
4378 # should be okay. B; A->B
4379
4380 B.addPatchset()
4381 B.data['commitMessage'] = '%s\n' % (B.subject,)
4382 source._getChange(u'1', u'2', True)
4383 source._getChange(u'2', u'2', True)
4384
Joshua Hesketh89e829d2015-02-10 16:29:45 +11004385 def test_disable_at(self):
4386 "Test a pipeline will only report to the disabled trigger when failing"
4387
4388 self.config.set('zuul', 'layout_config',
4389 'tests/fixtures/layout-disable-at.yaml')
4390 self.sched.reconfigure(self.config)
4391
4392 self.assertEqual(3, self.sched.layout.pipelines['check'].disable_at)
4393 self.assertEqual(
4394 0, self.sched.layout.pipelines['check']._consecutive_failures)
4395 self.assertFalse(self.sched.layout.pipelines['check']._disabled)
4396
4397 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
4398 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
4399 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
4400 D = self.fake_gerrit.addFakeChange('org/project', 'master', 'D')
4401 E = self.fake_gerrit.addFakeChange('org/project', 'master', 'E')
4402 F = self.fake_gerrit.addFakeChange('org/project', 'master', 'F')
4403 G = self.fake_gerrit.addFakeChange('org/project', 'master', 'G')
4404 H = self.fake_gerrit.addFakeChange('org/project', 'master', 'H')
4405 I = self.fake_gerrit.addFakeChange('org/project', 'master', 'I')
4406 J = self.fake_gerrit.addFakeChange('org/project', 'master', 'J')
4407 K = self.fake_gerrit.addFakeChange('org/project', 'master', 'K')
4408
4409 self.worker.addFailTest('project-test1', A)
4410 self.worker.addFailTest('project-test1', B)
4411 # Let C pass, resetting the counter
4412 self.worker.addFailTest('project-test1', D)
4413 self.worker.addFailTest('project-test1', E)
4414 self.worker.addFailTest('project-test1', F)
4415 self.worker.addFailTest('project-test1', G)
4416 self.worker.addFailTest('project-test1', H)
4417 # I also passes but should only report to the disabled reporters
4418 self.worker.addFailTest('project-test1', J)
4419 self.worker.addFailTest('project-test1', K)
4420
4421 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
4422 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
4423 self.waitUntilSettled()
4424
4425 self.assertEqual(
4426 2, self.sched.layout.pipelines['check']._consecutive_failures)
4427 self.assertFalse(self.sched.layout.pipelines['check']._disabled)
4428
4429 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
4430 self.waitUntilSettled()
4431
4432 self.assertEqual(
4433 0, self.sched.layout.pipelines['check']._consecutive_failures)
4434 self.assertFalse(self.sched.layout.pipelines['check']._disabled)
4435
4436 self.fake_gerrit.addEvent(D.getPatchsetCreatedEvent(1))
4437 self.fake_gerrit.addEvent(E.getPatchsetCreatedEvent(1))
4438 self.fake_gerrit.addEvent(F.getPatchsetCreatedEvent(1))
4439 self.waitUntilSettled()
4440
4441 # We should be disabled now
4442 self.assertEqual(
4443 3, self.sched.layout.pipelines['check']._consecutive_failures)
4444 self.assertTrue(self.sched.layout.pipelines['check']._disabled)
4445
4446 # We need to wait between each of these patches to make sure the
4447 # smtp messages come back in an expected order
4448 self.fake_gerrit.addEvent(G.getPatchsetCreatedEvent(1))
4449 self.waitUntilSettled()
4450 self.fake_gerrit.addEvent(H.getPatchsetCreatedEvent(1))
4451 self.waitUntilSettled()
4452 self.fake_gerrit.addEvent(I.getPatchsetCreatedEvent(1))
4453 self.waitUntilSettled()
4454
4455 # The first 6 (ABCDEF) jobs should have reported back to gerrt thus
4456 # leaving a message on each change
4457 self.assertEqual(1, len(A.messages))
4458 self.assertIn('Build failed.', A.messages[0])
4459 self.assertEqual(1, len(B.messages))
4460 self.assertIn('Build failed.', B.messages[0])
4461 self.assertEqual(1, len(C.messages))
4462 self.assertIn('Build succeeded.', C.messages[0])
4463 self.assertEqual(1, len(D.messages))
4464 self.assertIn('Build failed.', D.messages[0])
4465 self.assertEqual(1, len(E.messages))
4466 self.assertIn('Build failed.', E.messages[0])
4467 self.assertEqual(1, len(F.messages))
4468 self.assertIn('Build failed.', F.messages[0])
4469
4470 # The last 3 (GHI) would have only reported via smtp.
4471 self.assertEqual(3, len(self.smtp_messages))
4472 self.assertEqual(0, len(G.messages))
4473 self.assertIn('Build failed.', self.smtp_messages[0]['body'])
4474 self.assertIn('/7/1/check', self.smtp_messages[0]['body'])
4475 self.assertEqual(0, len(H.messages))
4476 self.assertIn('Build failed.', self.smtp_messages[1]['body'])
4477 self.assertIn('/8/1/check', self.smtp_messages[1]['body'])
4478 self.assertEqual(0, len(I.messages))
4479 self.assertIn('Build succeeded.', self.smtp_messages[2]['body'])
4480 self.assertIn('/9/1/check', self.smtp_messages[2]['body'])
4481
4482 # Now reload the configuration (simulate a HUP) to check the pipeline
4483 # comes out of disabled
4484 self.sched.reconfigure(self.config)
4485
4486 self.assertEqual(3, self.sched.layout.pipelines['check'].disable_at)
4487 self.assertEqual(
4488 0, self.sched.layout.pipelines['check']._consecutive_failures)
4489 self.assertFalse(self.sched.layout.pipelines['check']._disabled)
4490
4491 self.fake_gerrit.addEvent(J.getPatchsetCreatedEvent(1))
4492 self.fake_gerrit.addEvent(K.getPatchsetCreatedEvent(1))
4493 self.waitUntilSettled()
4494
4495 self.assertEqual(
4496 2, self.sched.layout.pipelines['check']._consecutive_failures)
4497 self.assertFalse(self.sched.layout.pipelines['check']._disabled)
4498
4499 # J and K went back to gerrit
4500 self.assertEqual(1, len(J.messages))
4501 self.assertIn('Build failed.', J.messages[0])
4502 self.assertEqual(1, len(K.messages))
4503 self.assertIn('Build failed.', K.messages[0])
4504 # No more messages reported via smtp
4505 self.assertEqual(3, len(self.smtp_messages))
Joshua Heskethd6dbd682015-12-22 10:06:54 +11004506
4507 def test_success_pattern(self):
4508 "Ensure bad build params are ignored"
4509
4510 # Use SMTP reporter to grab the result message easier
4511 self.init_repo("org/docs")
4512 self.config.set('zuul', 'layout_config',
4513 'tests/fixtures/layout-success-pattern.yaml')
4514 self.sched.reconfigure(self.config)
4515 self.worker.hold_jobs_in_build = True
4516 self.registerJobs()
4517
4518 A = self.fake_gerrit.addFakeChange('org/docs', 'master', 'A')
4519 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
4520 self.waitUntilSettled()
4521
4522 # Grab build id
4523 self.assertEqual(len(self.builds), 1)
4524 uuid = self.builds[0].unique[:7]
4525
4526 self.worker.hold_jobs_in_build = False
4527 self.worker.release()
4528 self.waitUntilSettled()
4529
4530 self.assertEqual(len(self.smtp_messages), 1)
4531 body = self.smtp_messages[0]['body'].splitlines()
4532 self.assertEqual('Build succeeded.', body[0])
4533
4534 self.assertIn(
4535 '- docs-draft-test http://docs-draft.example.org/1/1/1/check/'
4536 'docs-draft-test/%s/publish-docs/' % uuid,
4537 body[2])
4538 self.assertIn(
4539 '- docs-draft-test2 https://server/job/docs-draft-test2/1/',
4540 body[3])