blob: dcf7a8bf7d4db899f7dd80331316786bcc7f4ed2 [file] [log] [blame]
James E. Blairb0fcae42012-07-17 11:12:10 -07001#!/usr/bin/env python
2
3# Copyright 2012 Hewlett-Packard Development Company, L.P.
4#
5# Licensed under the Apache License, Version 2.0 (the "License"); you may
6# not use this file except in compliance with the License. You may obtain
7# a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations
15# under the License.
16
James E. Blairb0fcae42012-07-17 11:12:10 -070017import json
Monty Taylorbc758832013-06-17 17:22:42 -040018import logging
19import os
James E. Blairb0fcae42012-07-17 11:12:10 -070020import re
James E. Blair4886cc12012-07-18 15:39:41 -070021import shutil
Monty Taylorbc758832013-06-17 17:22:42 -040022import time
James E. Blair1843a552013-07-03 14:19:52 -070023import urllib
Monty Taylorbc758832013-06-17 17:22:42 -040024import urllib2
Monty Taylorbc758832013-06-17 17:22:42 -040025
James E. Blair4886cc12012-07-18 15:39:41 -070026import git
Monty Taylorbc758832013-06-17 17:22:42 -040027import testtools
James E. Blairb0fcae42012-07-17 11:12:10 -070028
James E. Blairb0fcae42012-07-17 11:12:10 -070029import zuul.scheduler
James E. Blairad28e912013-11-27 10:43:22 -080030import zuul.rpcclient
Joshua Hesketh1879cf72013-08-19 14:13:15 +100031import zuul.reporter.gerrit
Joshua Hesketh5fea8672013-08-19 17:32:01 +100032import zuul.reporter.smtp
James E. Blairb0fcae42012-07-17 11:12:10 -070033
Clark Boylanb640e052014-04-03 16:41:46 -070034from tests.base import ZuulTestCase, repack_repo
James E. Blairb0fcae42012-07-17 11:12:10 -070035
James E. Blair1f4c2bb2013-04-26 08:40:46 -070036logging.basicConfig(level=logging.DEBUG,
37 format='%(asctime)s %(name)-32s '
38 '%(levelname)-8s %(message)s')
James E. Blairb0fcae42012-07-17 11:12:10 -070039
40
Clark Boylanb640e052014-04-03 16:41:46 -070041class TestScheduler(ZuulTestCase):
Antoine Mussobd86a312014-01-08 14:51:33 +010042
James E. Blairb0fcae42012-07-17 11:12:10 -070043 def test_jobs_launched(self):
44 "Test that jobs are launched and a change is merged"
James E. Blair1f4c2bb2013-04-26 08:40:46 -070045
James E. Blairb0fcae42012-07-17 11:12:10 -070046 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
James E. Blair8c803f82012-07-31 16:25:42 -070047 A.addApproval('CRVW', 2)
James E. Blairb0fcae42012-07-17 11:12:10 -070048 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
49 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -040050 self.assertEqual(self.getJobFromHistory('project-merge').result,
51 'SUCCESS')
52 self.assertEqual(self.getJobFromHistory('project-test1').result,
53 'SUCCESS')
54 self.assertEqual(self.getJobFromHistory('project-test2').result,
55 'SUCCESS')
56 self.assertEqual(A.data['status'], 'MERGED')
57 self.assertEqual(A.reported, 2)
James E. Blairb0fcae42012-07-17 11:12:10 -070058
James E. Blair66eeebf2013-07-27 17:44:32 -070059 self.assertReportedStat('gerrit.event.comment-added', value='1|c')
60 self.assertReportedStat('zuul.pipeline.gate.current_changes',
61 value='1|g')
62 self.assertReportedStat('zuul.pipeline.gate.job.project-merge.SUCCESS',
63 kind='ms')
64 self.assertReportedStat('zuul.pipeline.gate.job.project-merge.SUCCESS',
65 value='1|c')
66 self.assertReportedStat('zuul.pipeline.gate.resident_time', kind='ms')
67 self.assertReportedStat('zuul.pipeline.gate.total_changes',
68 value='1|c')
James E. Blair412e5582013-04-22 15:50:12 -070069 self.assertReportedStat(
James E. Blair66eeebf2013-07-27 17:44:32 -070070 'zuul.pipeline.gate.org.project.resident_time', kind='ms')
James E. Blair412e5582013-04-22 15:50:12 -070071 self.assertReportedStat(
James E. Blair66eeebf2013-07-27 17:44:32 -070072 'zuul.pipeline.gate.org.project.total_changes', value='1|c')
James E. Blair412e5582013-04-22 15:50:12 -070073
James E. Blair3cb10702013-08-24 08:56:03 -070074 def test_initial_pipeline_gauges(self):
75 "Test that each pipeline reported its length on start"
76 pipeline_names = self.sched.layout.pipelines.keys()
77 self.assertNotEqual(len(pipeline_names), 0)
78 for name in pipeline_names:
79 self.assertReportedStat('zuul.pipeline.%s.current_changes' % name,
80 value='0|g')
81
James E. Blair42f74822013-05-14 15:18:03 -070082 def test_duplicate_pipelines(self):
83 "Test that a change matching multiple pipelines works"
James E. Blair1b4d9722013-05-21 10:32:04 -070084
James E. Blair42f74822013-05-14 15:18:03 -070085 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
86 self.fake_gerrit.addEvent(A.getChangeRestoredEvent())
87 self.waitUntilSettled()
James E. Blair42f74822013-05-14 15:18:03 -070088
Monty Taylor98f0f3e2013-07-06 16:02:31 -040089 self.assertEqual(len(self.history), 2)
Monty Taylor6bef8ef2013-06-02 08:17:12 -040090 self.history[0].name == 'project-test1'
91 self.history[1].name == 'project-test1'
James E. Blair42f74822013-05-14 15:18:03 -070092
Monty Taylor98f0f3e2013-07-06 16:02:31 -040093 self.assertEqual(len(A.messages), 2)
James E. Blair42f74822013-05-14 15:18:03 -070094 if 'dup1/project-test1' in A.messages[0]:
Monty Taylor98f0f3e2013-07-06 16:02:31 -040095 self.assertIn('dup1/project-test1', A.messages[0])
96 self.assertNotIn('dup2/project-test1', A.messages[0])
97 self.assertNotIn('dup1/project-test1', A.messages[1])
98 self.assertIn('dup2/project-test1', A.messages[1])
James E. Blair42f74822013-05-14 15:18:03 -070099 else:
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400100 self.assertIn('dup1/project-test1', A.messages[1])
101 self.assertNotIn('dup2/project-test1', A.messages[1])
102 self.assertNotIn('dup1/project-test1', A.messages[0])
103 self.assertIn('dup2/project-test1', A.messages[0])
James E. Blair42f74822013-05-14 15:18:03 -0700104
James E. Blairb0fcae42012-07-17 11:12:10 -0700105 def test_parallel_changes(self):
106 "Test that changes are tested in parallel and merged in series"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700107
108 self.worker.hold_jobs_in_build = True
James E. Blairb0fcae42012-07-17 11:12:10 -0700109 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
110 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
111 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
James E. Blair8c803f82012-07-31 16:25:42 -0700112 A.addApproval('CRVW', 2)
113 B.addApproval('CRVW', 2)
114 C.addApproval('CRVW', 2)
James E. Blairb0fcae42012-07-17 11:12:10 -0700115
116 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
117 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
118 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
119
120 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400121 self.assertEqual(len(self.builds), 1)
122 self.assertEqual(self.builds[0].name, 'project-merge')
123 self.assertTrue(self.job_has_changes(self.builds[0], A))
James E. Blairb0fcae42012-07-17 11:12:10 -0700124
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700125 self.worker.release('.*-merge')
James E. Blairb0fcae42012-07-17 11:12:10 -0700126 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400127 self.assertEqual(len(self.builds), 3)
128 self.assertEqual(self.builds[0].name, 'project-test1')
129 self.assertTrue(self.job_has_changes(self.builds[0], A))
130 self.assertEqual(self.builds[1].name, 'project-test2')
131 self.assertTrue(self.job_has_changes(self.builds[1], A))
132 self.assertEqual(self.builds[2].name, 'project-merge')
133 self.assertTrue(self.job_has_changes(self.builds[2], A, B))
James E. Blairb0fcae42012-07-17 11:12:10 -0700134
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700135 self.worker.release('.*-merge')
James E. Blairb0fcae42012-07-17 11:12:10 -0700136 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400137 self.assertEqual(len(self.builds), 5)
138 self.assertEqual(self.builds[0].name, 'project-test1')
139 self.assertTrue(self.job_has_changes(self.builds[0], A))
140 self.assertEqual(self.builds[1].name, 'project-test2')
141 self.assertTrue(self.job_has_changes(self.builds[1], A))
James E. Blairb0fcae42012-07-17 11:12:10 -0700142
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400143 self.assertEqual(self.builds[2].name, 'project-test1')
144 self.assertTrue(self.job_has_changes(self.builds[2], A, B))
145 self.assertEqual(self.builds[3].name, 'project-test2')
146 self.assertTrue(self.job_has_changes(self.builds[3], A, B))
James E. Blairb0fcae42012-07-17 11:12:10 -0700147
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400148 self.assertEqual(self.builds[4].name, 'project-merge')
149 self.assertTrue(self.job_has_changes(self.builds[4], A, B, C))
James E. Blairb0fcae42012-07-17 11:12:10 -0700150
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700151 self.worker.release('.*-merge')
James E. Blairb0fcae42012-07-17 11:12:10 -0700152 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400153 self.assertEqual(len(self.builds), 6)
154 self.assertEqual(self.builds[0].name, 'project-test1')
155 self.assertTrue(self.job_has_changes(self.builds[0], A))
156 self.assertEqual(self.builds[1].name, 'project-test2')
157 self.assertTrue(self.job_has_changes(self.builds[1], A))
James E. Blairb0fcae42012-07-17 11:12:10 -0700158
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400159 self.assertEqual(self.builds[2].name, 'project-test1')
160 self.assertTrue(self.job_has_changes(self.builds[2], A, B))
161 self.assertEqual(self.builds[3].name, 'project-test2')
162 self.assertTrue(self.job_has_changes(self.builds[3], A, B))
James E. Blairb0fcae42012-07-17 11:12:10 -0700163
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400164 self.assertEqual(self.builds[4].name, 'project-test1')
165 self.assertTrue(self.job_has_changes(self.builds[4], A, B, C))
166 self.assertEqual(self.builds[5].name, 'project-test2')
167 self.assertTrue(self.job_has_changes(self.builds[5], A, B, C))
James E. Blairb0fcae42012-07-17 11:12:10 -0700168
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700169 self.worker.hold_jobs_in_build = False
170 self.worker.release()
James E. Blairb0fcae42012-07-17 11:12:10 -0700171 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400172 self.assertEqual(len(self.builds), 0)
James E. Blairb0fcae42012-07-17 11:12:10 -0700173
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400174 self.assertEqual(len(self.history), 9)
175 self.assertEqual(A.data['status'], 'MERGED')
176 self.assertEqual(B.data['status'], 'MERGED')
177 self.assertEqual(C.data['status'], 'MERGED')
178 self.assertEqual(A.reported, 2)
179 self.assertEqual(B.reported, 2)
180 self.assertEqual(C.reported, 2)
James E. Blairb02a3bb2012-07-30 17:49:55 -0700181
182 def test_failed_changes(self):
183 "Test that a change behind a failed change is retested"
James E. Blaire2819012013-06-28 17:17:26 -0400184 self.worker.hold_jobs_in_build = True
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700185
James E. Blairb02a3bb2012-07-30 17:49:55 -0700186 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
187 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
James E. Blair8c803f82012-07-31 16:25:42 -0700188 A.addApproval('CRVW', 2)
189 B.addApproval('CRVW', 2)
James E. Blairb02a3bb2012-07-30 17:49:55 -0700190
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700191 self.worker.addFailTest('project-test1', A)
James E. Blairb02a3bb2012-07-30 17:49:55 -0700192
James E. Blaire2819012013-06-28 17:17:26 -0400193 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
194 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
James E. Blairb02a3bb2012-07-30 17:49:55 -0700195 self.waitUntilSettled()
James E. Blaire2819012013-06-28 17:17:26 -0400196
197 self.worker.release('.*-merge')
198 self.waitUntilSettled()
199
200 self.worker.hold_jobs_in_build = False
201 self.worker.release()
202
203 self.waitUntilSettled()
204 # It's certain that the merge job for change 2 will run, but
205 # the test1 and test2 jobs may or may not run.
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400206 self.assertTrue(len(self.history) > 6)
207 self.assertEqual(A.data['status'], 'NEW')
208 self.assertEqual(B.data['status'], 'MERGED')
209 self.assertEqual(A.reported, 2)
210 self.assertEqual(B.reported, 2)
James E. Blairb02a3bb2012-07-30 17:49:55 -0700211
212 def test_independent_queues(self):
213 "Test that changes end up in the right queues"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700214
215 self.worker.hold_jobs_in_build = True
Zhongyue Luo5d556072012-09-21 02:00:47 +0900216 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
James E. Blairb02a3bb2012-07-30 17:49:55 -0700217 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
218 C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
James E. Blair8c803f82012-07-31 16:25:42 -0700219 A.addApproval('CRVW', 2)
220 B.addApproval('CRVW', 2)
221 C.addApproval('CRVW', 2)
James E. Blairb02a3bb2012-07-30 17:49:55 -0700222
223 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
224 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
225 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
226
James E. Blairb02a3bb2012-07-30 17:49:55 -0700227 self.waitUntilSettled()
228
229 # There should be one merge job at the head of each queue running
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400230 self.assertEqual(len(self.builds), 2)
231 self.assertEqual(self.builds[0].name, 'project-merge')
232 self.assertTrue(self.job_has_changes(self.builds[0], A))
233 self.assertEqual(self.builds[1].name, 'project1-merge')
234 self.assertTrue(self.job_has_changes(self.builds[1], B))
James E. Blairb02a3bb2012-07-30 17:49:55 -0700235
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700236 # Release the current merge builds
237 self.worker.release('.*-merge')
James E. Blairb02a3bb2012-07-30 17:49:55 -0700238 self.waitUntilSettled()
239 # Release the merge job for project2 which is behind project1
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700240 self.worker.release('.*-merge')
James E. Blairb02a3bb2012-07-30 17:49:55 -0700241 self.waitUntilSettled()
242
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700243 # All the test builds should be running:
James E. Blairb02a3bb2012-07-30 17:49:55 -0700244 # project1 (3) + project2 (3) + project (2) = 8
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400245 self.assertEqual(len(self.builds), 8)
James E. Blairb02a3bb2012-07-30 17:49:55 -0700246
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700247 self.worker.release()
James E. Blairb02a3bb2012-07-30 17:49:55 -0700248 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400249 self.assertEqual(len(self.builds), 0)
James E. Blairb02a3bb2012-07-30 17:49:55 -0700250
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400251 self.assertEqual(len(self.history), 11)
252 self.assertEqual(A.data['status'], 'MERGED')
253 self.assertEqual(B.data['status'], 'MERGED')
254 self.assertEqual(C.data['status'], 'MERGED')
255 self.assertEqual(A.reported, 2)
256 self.assertEqual(B.reported, 2)
257 self.assertEqual(C.reported, 2)
James E. Blaird466dc42012-07-31 10:42:56 -0700258
259 def test_failed_change_at_head(self):
260 "Test that if a change at the head fails, jobs behind it are canceled"
James E. Blaird466dc42012-07-31 10:42:56 -0700261
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700262 self.worker.hold_jobs_in_build = True
James E. Blaird466dc42012-07-31 10:42:56 -0700263 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
264 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
265 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
James E. Blair8c803f82012-07-31 16:25:42 -0700266 A.addApproval('CRVW', 2)
267 B.addApproval('CRVW', 2)
268 C.addApproval('CRVW', 2)
James E. Blaird466dc42012-07-31 10:42:56 -0700269
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700270 self.worker.addFailTest('project-test1', A)
James E. Blaird466dc42012-07-31 10:42:56 -0700271
272 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
273 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
274 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
275
276 self.waitUntilSettled()
James E. Blaird466dc42012-07-31 10:42:56 -0700277
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400278 self.assertEqual(len(self.builds), 1)
279 self.assertEqual(self.builds[0].name, 'project-merge')
280 self.assertTrue(self.job_has_changes(self.builds[0], A))
James E. Blaird466dc42012-07-31 10:42:56 -0700281
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700282 self.worker.release('.*-merge')
James E. Blaird466dc42012-07-31 10:42:56 -0700283 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700284 self.worker.release('.*-merge')
James E. Blaird466dc42012-07-31 10:42:56 -0700285 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700286 self.worker.release('.*-merge')
James E. Blaird466dc42012-07-31 10:42:56 -0700287 self.waitUntilSettled()
288
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400289 self.assertEqual(len(self.builds), 6)
290 self.assertEqual(self.builds[0].name, 'project-test1')
291 self.assertEqual(self.builds[1].name, 'project-test2')
292 self.assertEqual(self.builds[2].name, 'project-test1')
293 self.assertEqual(self.builds[3].name, 'project-test2')
294 self.assertEqual(self.builds[4].name, 'project-test1')
295 self.assertEqual(self.builds[5].name, 'project-test2')
James E. Blaird466dc42012-07-31 10:42:56 -0700296
Monty Taylor6bef8ef2013-06-02 08:17:12 -0400297 self.release(self.builds[0])
James E. Blaird466dc42012-07-31 10:42:56 -0700298 self.waitUntilSettled()
299
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400300 # project-test2, project-merge for B
301 self.assertEqual(len(self.builds), 2)
302 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 4)
James E. Blaird466dc42012-07-31 10:42:56 -0700303
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700304 self.worker.hold_jobs_in_build = False
305 self.worker.release()
James E. Blaird466dc42012-07-31 10:42:56 -0700306 self.waitUntilSettled()
307
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400308 self.assertEqual(len(self.builds), 0)
309 self.assertEqual(len(self.history), 15)
310 self.assertEqual(A.data['status'], 'NEW')
311 self.assertEqual(B.data['status'], 'MERGED')
312 self.assertEqual(C.data['status'], 'MERGED')
313 self.assertEqual(A.reported, 2)
314 self.assertEqual(B.reported, 2)
315 self.assertEqual(C.reported, 2)
James E. Blaird466dc42012-07-31 10:42:56 -0700316
James E. Blair0aac4872013-08-23 14:02:38 -0700317 def test_failed_change_in_middle(self):
318 "Test a failed change in the middle of the queue"
319
320 self.worker.hold_jobs_in_build = True
321 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
322 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
323 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
324 A.addApproval('CRVW', 2)
325 B.addApproval('CRVW', 2)
326 C.addApproval('CRVW', 2)
327
328 self.worker.addFailTest('project-test1', B)
329
330 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
331 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
332 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
333
334 self.waitUntilSettled()
335
336 self.worker.release('.*-merge')
337 self.waitUntilSettled()
338 self.worker.release('.*-merge')
339 self.waitUntilSettled()
340 self.worker.release('.*-merge')
341 self.waitUntilSettled()
342
343 self.assertEqual(len(self.builds), 6)
344 self.assertEqual(self.builds[0].name, 'project-test1')
345 self.assertEqual(self.builds[1].name, 'project-test2')
346 self.assertEqual(self.builds[2].name, 'project-test1')
347 self.assertEqual(self.builds[3].name, 'project-test2')
348 self.assertEqual(self.builds[4].name, 'project-test1')
349 self.assertEqual(self.builds[5].name, 'project-test2')
350
351 self.release(self.builds[2])
352 self.waitUntilSettled()
353
James E. Blair972e3c72013-08-29 12:04:55 -0700354 # project-test1 and project-test2 for A
355 # project-test2 for B
356 # project-merge for C (without B)
357 self.assertEqual(len(self.builds), 4)
James E. Blair0aac4872013-08-23 14:02:38 -0700358 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 2)
359
James E. Blair972e3c72013-08-29 12:04:55 -0700360 self.worker.release('.*-merge')
361 self.waitUntilSettled()
362
363 # project-test1 and project-test2 for A
364 # project-test2 for B
365 # project-test1 and project-test2 for C
366 self.assertEqual(len(self.builds), 5)
367
James E. Blair0aac4872013-08-23 14:02:38 -0700368 items = self.sched.layout.pipelines['gate'].getAllItems()
369 builds = items[0].current_build_set.getBuilds()
370 self.assertEqual(self.countJobResults(builds, 'SUCCESS'), 1)
371 self.assertEqual(self.countJobResults(builds, None), 2)
372 builds = items[1].current_build_set.getBuilds()
373 self.assertEqual(self.countJobResults(builds, 'SUCCESS'), 1)
374 self.assertEqual(self.countJobResults(builds, 'FAILURE'), 1)
375 self.assertEqual(self.countJobResults(builds, None), 1)
376 builds = items[2].current_build_set.getBuilds()
377 self.assertEqual(self.countJobResults(builds, 'SUCCESS'), 1)
James E. Blair972e3c72013-08-29 12:04:55 -0700378 self.assertEqual(self.countJobResults(builds, None), 2)
James E. Blair0aac4872013-08-23 14:02:38 -0700379
380 self.worker.hold_jobs_in_build = False
381 self.worker.release()
382 self.waitUntilSettled()
383
384 self.assertEqual(len(self.builds), 0)
385 self.assertEqual(len(self.history), 12)
386 self.assertEqual(A.data['status'], 'MERGED')
387 self.assertEqual(B.data['status'], 'NEW')
388 self.assertEqual(C.data['status'], 'MERGED')
389 self.assertEqual(A.reported, 2)
390 self.assertEqual(B.reported, 2)
391 self.assertEqual(C.reported, 2)
392
James E. Blaird466dc42012-07-31 10:42:56 -0700393 def test_failed_change_at_head_with_queue(self):
394 "Test that if a change at the head fails, queued jobs are canceled"
James E. Blaird466dc42012-07-31 10:42:56 -0700395
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700396 self.gearman_server.hold_jobs_in_queue = True
James E. Blaird466dc42012-07-31 10:42:56 -0700397 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
398 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
399 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
James E. Blair8c803f82012-07-31 16:25:42 -0700400 A.addApproval('CRVW', 2)
401 B.addApproval('CRVW', 2)
402 C.addApproval('CRVW', 2)
James E. Blaird466dc42012-07-31 10:42:56 -0700403
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700404 self.worker.addFailTest('project-test1', A)
James E. Blaird466dc42012-07-31 10:42:56 -0700405
406 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
407 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
408 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
409
410 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -0700411 queue = self.gearman_server.getQueue()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400412 self.assertEqual(len(self.builds), 0)
413 self.assertEqual(len(queue), 1)
414 self.assertEqual(queue[0].name, 'build:project-merge')
415 self.assertTrue(self.job_has_changes(queue[0], A))
James E. Blaird466dc42012-07-31 10:42:56 -0700416
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700417 self.gearman_server.release('.*-merge')
James E. Blaird466dc42012-07-31 10:42:56 -0700418 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700419 self.gearman_server.release('.*-merge')
James E. Blaird466dc42012-07-31 10:42:56 -0700420 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700421 self.gearman_server.release('.*-merge')
James E. Blaird466dc42012-07-31 10:42:56 -0700422 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -0700423 queue = self.gearman_server.getQueue()
James E. Blaird466dc42012-07-31 10:42:56 -0700424
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400425 self.assertEqual(len(self.builds), 0)
426 self.assertEqual(len(queue), 6)
427 self.assertEqual(queue[0].name, 'build:project-test1')
428 self.assertEqual(queue[1].name, 'build:project-test2')
429 self.assertEqual(queue[2].name, 'build:project-test1')
430 self.assertEqual(queue[3].name, 'build:project-test2')
431 self.assertEqual(queue[4].name, 'build:project-test1')
432 self.assertEqual(queue[5].name, 'build:project-test2')
James E. Blaird466dc42012-07-31 10:42:56 -0700433
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700434 self.release(queue[0])
James E. Blaird466dc42012-07-31 10:42:56 -0700435 self.waitUntilSettled()
436
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400437 self.assertEqual(len(self.builds), 0)
James E. Blair701c5b42013-06-06 09:34:59 -0700438 queue = self.gearman_server.getQueue()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400439 self.assertEqual(len(queue), 2) # project-test2, project-merge for B
440 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 0)
James E. Blaird466dc42012-07-31 10:42:56 -0700441
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700442 self.gearman_server.hold_jobs_in_queue = False
443 self.gearman_server.release()
James E. Blaird466dc42012-07-31 10:42:56 -0700444 self.waitUntilSettled()
445
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400446 self.assertEqual(len(self.builds), 0)
447 self.assertEqual(len(self.history), 11)
448 self.assertEqual(A.data['status'], 'NEW')
449 self.assertEqual(B.data['status'], 'MERGED')
450 self.assertEqual(C.data['status'], 'MERGED')
451 self.assertEqual(A.reported, 2)
452 self.assertEqual(B.reported, 2)
453 self.assertEqual(C.reported, 2)
James E. Blair8c803f82012-07-31 16:25:42 -0700454
James E. Blairfef71632013-09-23 11:15:47 -0700455 def test_two_failed_changes_at_head(self):
456 "Test that changes are reparented correctly if 2 fail at head"
457
458 self.worker.hold_jobs_in_build = True
459 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
460 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
461 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
462 A.addApproval('CRVW', 2)
463 B.addApproval('CRVW', 2)
464 C.addApproval('CRVW', 2)
465
466 self.worker.addFailTest('project-test1', A)
467 self.worker.addFailTest('project-test1', B)
468
469 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
470 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
471 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
472 self.waitUntilSettled()
473
474 self.worker.release('.*-merge')
475 self.waitUntilSettled()
476 self.worker.release('.*-merge')
477 self.waitUntilSettled()
478 self.worker.release('.*-merge')
479 self.waitUntilSettled()
480
481 self.assertEqual(len(self.builds), 6)
482 self.assertEqual(self.builds[0].name, 'project-test1')
483 self.assertEqual(self.builds[1].name, 'project-test2')
484 self.assertEqual(self.builds[2].name, 'project-test1')
485 self.assertEqual(self.builds[3].name, 'project-test2')
486 self.assertEqual(self.builds[4].name, 'project-test1')
487 self.assertEqual(self.builds[5].name, 'project-test2')
488
489 self.assertTrue(self.job_has_changes(self.builds[0], A))
490 self.assertTrue(self.job_has_changes(self.builds[2], A))
491 self.assertTrue(self.job_has_changes(self.builds[2], B))
492 self.assertTrue(self.job_has_changes(self.builds[4], A))
493 self.assertTrue(self.job_has_changes(self.builds[4], B))
494 self.assertTrue(self.job_has_changes(self.builds[4], C))
495
496 # Fail change B first
497 self.release(self.builds[2])
498 self.waitUntilSettled()
499
500 # restart of C after B failure
501 self.worker.release('.*-merge')
502 self.waitUntilSettled()
503
504 self.assertEqual(len(self.builds), 5)
505 self.assertEqual(self.builds[0].name, 'project-test1')
506 self.assertEqual(self.builds[1].name, 'project-test2')
507 self.assertEqual(self.builds[2].name, 'project-test2')
508 self.assertEqual(self.builds[3].name, 'project-test1')
509 self.assertEqual(self.builds[4].name, 'project-test2')
510
511 self.assertTrue(self.job_has_changes(self.builds[1], A))
512 self.assertTrue(self.job_has_changes(self.builds[2], A))
513 self.assertTrue(self.job_has_changes(self.builds[2], B))
514 self.assertTrue(self.job_has_changes(self.builds[4], A))
515 self.assertFalse(self.job_has_changes(self.builds[4], B))
516 self.assertTrue(self.job_has_changes(self.builds[4], C))
517
518 # Finish running all passing jobs for change A
519 self.release(self.builds[1])
520 self.waitUntilSettled()
521 # Fail and report change A
522 self.release(self.builds[0])
523 self.waitUntilSettled()
524
525 # restart of B,C after A failure
526 self.worker.release('.*-merge')
527 self.waitUntilSettled()
528 self.worker.release('.*-merge')
529 self.waitUntilSettled()
530
531 self.assertEqual(len(self.builds), 4)
532 self.assertEqual(self.builds[0].name, 'project-test1') # B
533 self.assertEqual(self.builds[1].name, 'project-test2') # B
534 self.assertEqual(self.builds[2].name, 'project-test1') # C
535 self.assertEqual(self.builds[3].name, 'project-test2') # C
536
537 self.assertFalse(self.job_has_changes(self.builds[1], A))
538 self.assertTrue(self.job_has_changes(self.builds[1], B))
539 self.assertFalse(self.job_has_changes(self.builds[1], C))
540
541 self.assertFalse(self.job_has_changes(self.builds[2], A))
542 # After A failed and B and C restarted, B should be back in
543 # C's tests because it has not failed yet.
544 self.assertTrue(self.job_has_changes(self.builds[2], B))
545 self.assertTrue(self.job_has_changes(self.builds[2], C))
546
547 self.worker.hold_jobs_in_build = False
548 self.worker.release()
549 self.waitUntilSettled()
550
551 self.assertEqual(len(self.builds), 0)
552 self.assertEqual(len(self.history), 21)
553 self.assertEqual(A.data['status'], 'NEW')
554 self.assertEqual(B.data['status'], 'NEW')
555 self.assertEqual(C.data['status'], 'MERGED')
556 self.assertEqual(A.reported, 2)
557 self.assertEqual(B.reported, 2)
558 self.assertEqual(C.reported, 2)
559
James E. Blair8c803f82012-07-31 16:25:42 -0700560 def test_patch_order(self):
561 "Test that dependent patches are tested in the right order"
562 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
563 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
564 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
565 A.addApproval('CRVW', 2)
566 B.addApproval('CRVW', 2)
567 C.addApproval('CRVW', 2)
568
569 M2 = self.fake_gerrit.addFakeChange('org/project', 'master', 'M2')
570 M1 = self.fake_gerrit.addFakeChange('org/project', 'master', 'M1')
571 M2.setMerged()
572 M1.setMerged()
573
574 # C -> B -> A -> M1 -> M2
575 # M2 is here to make sure it is never queried. If it is, it
576 # means zuul is walking down the entire history of merged
577 # changes.
578
579 C.setDependsOn(B, 1)
580 B.setDependsOn(A, 1)
581 A.setDependsOn(M1, 1)
582 M1.setDependsOn(M2, 1)
583
584 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
585
586 self.waitUntilSettled()
587
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400588 self.assertEqual(A.data['status'], 'NEW')
589 self.assertEqual(B.data['status'], 'NEW')
590 self.assertEqual(C.data['status'], 'NEW')
James E. Blair8c803f82012-07-31 16:25:42 -0700591
592 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
593 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
594
595 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400596 self.assertEqual(M2.queried, 0)
597 self.assertEqual(A.data['status'], 'MERGED')
598 self.assertEqual(B.data['status'], 'MERGED')
599 self.assertEqual(C.data['status'], 'MERGED')
600 self.assertEqual(A.reported, 2)
601 self.assertEqual(B.reported, 2)
602 self.assertEqual(C.reported, 2)
James E. Blair8c803f82012-07-31 16:25:42 -0700603
James E. Blair063672f2015-01-29 13:09:12 -0800604 def test_needed_changes_enqueue(self):
605 "Test that a needed change is enqueued ahead"
606 # A Given a git tree like this, if we enqueue
607 # / \ change C, we should walk up and down the tree
608 # B G and enqueue changes in the order ABCDEFG.
609 # /|\ This is also the order that you would get if
610 # *C E F you enqueued changes in the order ABCDEFG, so
611 # / the ordering is stable across re-enqueue events.
612 # D
613
614 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
615 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
616 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
617 D = self.fake_gerrit.addFakeChange('org/project', 'master', 'D')
618 E = self.fake_gerrit.addFakeChange('org/project', 'master', 'E')
619 F = self.fake_gerrit.addFakeChange('org/project', 'master', 'F')
620 G = self.fake_gerrit.addFakeChange('org/project', 'master', 'G')
621 B.setDependsOn(A, 1)
622 C.setDependsOn(B, 1)
623 D.setDependsOn(C, 1)
624 E.setDependsOn(B, 1)
625 F.setDependsOn(B, 1)
626 G.setDependsOn(A, 1)
627
628 A.addApproval('CRVW', 2)
629 B.addApproval('CRVW', 2)
630 C.addApproval('CRVW', 2)
631 D.addApproval('CRVW', 2)
632 E.addApproval('CRVW', 2)
633 F.addApproval('CRVW', 2)
634 G.addApproval('CRVW', 2)
635 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
636
637 self.waitUntilSettled()
638
639 self.assertEqual(A.data['status'], 'NEW')
640 self.assertEqual(B.data['status'], 'NEW')
641 self.assertEqual(C.data['status'], 'NEW')
642 self.assertEqual(D.data['status'], 'NEW')
643 self.assertEqual(E.data['status'], 'NEW')
644 self.assertEqual(F.data['status'], 'NEW')
645 self.assertEqual(G.data['status'], 'NEW')
646
647 # We're about to add approvals to changes without adding the
648 # triggering events to Zuul, so that we can be sure that it is
649 # enqueing the changes based on dependencies, not because of
650 # triggering events. Since it will have the changes cached
651 # already (without approvals), we need to clear the cache
652 # first.
653 source = self.sched.layout.pipelines['gate'].source
654 source.maintainCache([])
655
656 self.worker.hold_jobs_in_build = True
657 A.addApproval('APRV', 1)
658 B.addApproval('APRV', 1)
659 D.addApproval('APRV', 1)
660 E.addApproval('APRV', 1)
661 F.addApproval('APRV', 1)
662 G.addApproval('APRV', 1)
663 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
664
665 for x in range(8):
666 self.worker.release('.*-merge')
667 self.waitUntilSettled()
668 self.worker.hold_jobs_in_build = False
669 self.worker.release()
670 self.waitUntilSettled()
671
672 self.assertEqual(A.data['status'], 'MERGED')
673 self.assertEqual(B.data['status'], 'MERGED')
674 self.assertEqual(C.data['status'], 'MERGED')
675 self.assertEqual(D.data['status'], 'MERGED')
676 self.assertEqual(E.data['status'], 'MERGED')
677 self.assertEqual(F.data['status'], 'MERGED')
678 self.assertEqual(G.data['status'], 'MERGED')
679 self.assertEqual(A.reported, 2)
680 self.assertEqual(B.reported, 2)
681 self.assertEqual(C.reported, 2)
682 self.assertEqual(D.reported, 2)
683 self.assertEqual(E.reported, 2)
684 self.assertEqual(F.reported, 2)
685 self.assertEqual(G.reported, 2)
686 self.assertEqual(self.history[6].changes,
687 '1,1 2,1 3,1 4,1 5,1 6,1 7,1')
688
James E. Blair0e933c52013-07-11 10:18:52 -0700689 def test_trigger_cache(self):
690 "Test that the trigger cache operates correctly"
691 self.worker.hold_jobs_in_build = True
692
693 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
694 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
695 X = self.fake_gerrit.addFakeChange('org/project', 'master', 'X')
696 A.addApproval('CRVW', 2)
697 B.addApproval('CRVW', 2)
698
699 M1 = self.fake_gerrit.addFakeChange('org/project', 'master', 'M1')
700 M1.setMerged()
701
702 B.setDependsOn(A, 1)
703 A.setDependsOn(M1, 1)
704
705 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
706 self.fake_gerrit.addEvent(X.getPatchsetCreatedEvent(1))
707
708 self.waitUntilSettled()
709
710 for build in self.builds:
711 if build.parameters['ZUUL_PIPELINE'] == 'check':
712 build.release()
713 self.waitUntilSettled()
714 for build in self.builds:
715 if build.parameters['ZUUL_PIPELINE'] == 'check':
716 build.release()
717 self.waitUntilSettled()
718
719 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
720 self.waitUntilSettled()
721
Antoine Mussof0506fa2014-06-03 15:03:38 +0200722 self.log.debug("len %s" % self.gerrit._change_cache.keys())
James E. Blair0e933c52013-07-11 10:18:52 -0700723 # there should still be changes in the cache
James E. Blair6c358e72013-07-29 17:06:47 -0700724 self.assertNotEqual(len(self.gerrit._change_cache.keys()), 0)
James E. Blair0e933c52013-07-11 10:18:52 -0700725
726 self.worker.hold_jobs_in_build = False
727 self.worker.release()
728 self.waitUntilSettled()
729
730 self.assertEqual(A.data['status'], 'MERGED')
731 self.assertEqual(B.data['status'], 'MERGED')
732 self.assertEqual(A.queried, 2) # Initial and isMerged
733 self.assertEqual(B.queried, 3) # Initial A, refresh from B, isMerged
734
James E. Blair8c803f82012-07-31 16:25:42 -0700735 def test_can_merge(self):
James E. Blair4886cc12012-07-18 15:39:41 -0700736 "Test whether a change is ready to merge"
James E. Blair8c803f82012-07-31 16:25:42 -0700737 # TODO: move to test_gerrit (this is a unit test!)
738 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
James E. Blairc0dedf82014-08-06 09:37:52 -0700739 source = self.sched.layout.pipelines['gate'].source
740 a = source._getChange(1, 2)
James E. Blaireff88162013-07-01 12:44:14 -0400741 mgr = self.sched.layout.pipelines['gate'].manager
James E. Blairc0dedf82014-08-06 09:37:52 -0700742 self.assertFalse(source.canMerge(a, mgr.getSubmitAllowNeeds()))
James E. Blair8c803f82012-07-31 16:25:42 -0700743
744 A.addApproval('CRVW', 2)
James E. Blairc0dedf82014-08-06 09:37:52 -0700745 a = source._getChange(1, 2, refresh=True)
746 self.assertFalse(source.canMerge(a, mgr.getSubmitAllowNeeds()))
James E. Blair8c803f82012-07-31 16:25:42 -0700747
748 A.addApproval('APRV', 1)
James E. Blairc0dedf82014-08-06 09:37:52 -0700749 a = source._getChange(1, 2, refresh=True)
750 self.assertTrue(source.canMerge(a, mgr.getSubmitAllowNeeds()))
751 source.maintainCache([])
James E. Blair4886cc12012-07-18 15:39:41 -0700752
753 def test_build_configuration(self):
754 "Test that zuul merges the right commits for testing"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700755
756 self.gearman_server.hold_jobs_in_queue = True
James E. Blair4886cc12012-07-18 15:39:41 -0700757 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
758 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
759 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
760 A.addApproval('CRVW', 2)
761 B.addApproval('CRVW', 2)
762 C.addApproval('CRVW', 2)
763 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
764 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
765 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
766 self.waitUntilSettled()
767
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700768 self.gearman_server.release('.*-merge')
James E. Blair4886cc12012-07-18 15:39:41 -0700769 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700770 self.gearman_server.release('.*-merge')
James E. Blair4886cc12012-07-18 15:39:41 -0700771 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700772 self.gearman_server.release('.*-merge')
James E. Blair4886cc12012-07-18 15:39:41 -0700773 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -0700774 queue = self.gearman_server.getQueue()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700775 ref = self.getParameter(queue[-1], 'ZUUL_REF')
776 self.gearman_server.hold_jobs_in_queue = False
777 self.gearman_server.release()
James E. Blair973721f2012-08-15 10:19:43 -0700778 self.waitUntilSettled()
James E. Blair4886cc12012-07-18 15:39:41 -0700779
Monty Taylorbc758832013-06-17 17:22:42 -0400780 path = os.path.join(self.git_root, "org/project")
James E. Blair4886cc12012-07-18 15:39:41 -0700781 repo = git.Repo(path)
782 repo_messages = [c.message.strip() for c in repo.iter_commits(ref)]
783 repo_messages.reverse()
James E. Blair4886cc12012-07-18 15:39:41 -0700784 correct_messages = ['initial commit', 'A-1', 'B-1', 'C-1']
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400785 self.assertEqual(repo_messages, correct_messages)
James E. Blair973721f2012-08-15 10:19:43 -0700786
787 def test_build_configuration_conflict(self):
788 "Test that merge conflicts are handled"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700789
790 self.gearman_server.hold_jobs_in_queue = True
James E. Blair6736beb2013-07-11 15:18:15 -0700791 A = self.fake_gerrit.addFakeChange('org/conflict-project',
792 'master', 'A')
James E. Blair973721f2012-08-15 10:19:43 -0700793 A.addPatchset(['conflict'])
James E. Blair6736beb2013-07-11 15:18:15 -0700794 B = self.fake_gerrit.addFakeChange('org/conflict-project',
795 'master', 'B')
James E. Blair973721f2012-08-15 10:19:43 -0700796 B.addPatchset(['conflict'])
James E. Blair6736beb2013-07-11 15:18:15 -0700797 C = self.fake_gerrit.addFakeChange('org/conflict-project',
798 'master', 'C')
James E. Blair973721f2012-08-15 10:19:43 -0700799 A.addApproval('CRVW', 2)
800 B.addApproval('CRVW', 2)
801 C.addApproval('CRVW', 2)
802 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
803 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
804 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
805 self.waitUntilSettled()
806
James E. Blair6736beb2013-07-11 15:18:15 -0700807 self.assertEqual(A.reported, 1)
808 self.assertEqual(B.reported, 1)
809 self.assertEqual(C.reported, 1)
810
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700811 self.gearman_server.release('.*-merge')
James E. Blair973721f2012-08-15 10:19:43 -0700812 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700813 self.gearman_server.release('.*-merge')
James E. Blair973721f2012-08-15 10:19:43 -0700814 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700815 self.gearman_server.release('.*-merge')
James E. Blair973721f2012-08-15 10:19:43 -0700816 self.waitUntilSettled()
James E. Blair972e3c72013-08-29 12:04:55 -0700817
818 self.assertEqual(len(self.history), 2) # A and C merge jobs
819
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700820 self.gearman_server.hold_jobs_in_queue = False
821 self.gearman_server.release()
James E. Blair973721f2012-08-15 10:19:43 -0700822 self.waitUntilSettled()
823
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400824 self.assertEqual(A.data['status'], 'MERGED')
825 self.assertEqual(B.data['status'], 'NEW')
826 self.assertEqual(C.data['status'], 'MERGED')
827 self.assertEqual(A.reported, 2)
828 self.assertEqual(B.reported, 2)
829 self.assertEqual(C.reported, 2)
James E. Blair972e3c72013-08-29 12:04:55 -0700830 self.assertEqual(len(self.history), 6)
James E. Blair6736beb2013-07-11 15:18:15 -0700831
James E. Blairdaabed22012-08-15 15:38:57 -0700832 def test_post(self):
833 "Test that post jobs run"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700834
Zhongyue Luo5d556072012-09-21 02:00:47 +0900835 e = {
836 "type": "ref-updated",
837 "submitter": {
838 "name": "User Name",
839 },
840 "refUpdate": {
841 "oldRev": "90f173846e3af9154517b88543ffbd1691f31366",
842 "newRev": "d479a0bfcb34da57a31adb2a595c0cf687812543",
843 "refName": "master",
844 "project": "org/project",
845 }
846 }
James E. Blairdaabed22012-08-15 15:38:57 -0700847 self.fake_gerrit.addEvent(e)
848 self.waitUntilSettled()
849
Monty Taylor6bef8ef2013-06-02 08:17:12 -0400850 job_names = [x.name for x in self.history]
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400851 self.assertEqual(len(self.history), 1)
852 self.assertIn('project-post', job_names)
James E. Blairc6294a52012-08-17 10:19:48 -0700853
854 def test_build_configuration_branch(self):
855 "Test that the right commits are on alternate branches"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700856
857 self.gearman_server.hold_jobs_in_queue = True
James E. Blairc6294a52012-08-17 10:19:48 -0700858 A = self.fake_gerrit.addFakeChange('org/project', 'mp', 'A')
859 B = self.fake_gerrit.addFakeChange('org/project', 'mp', 'B')
860 C = self.fake_gerrit.addFakeChange('org/project', 'mp', 'C')
861 A.addApproval('CRVW', 2)
862 B.addApproval('CRVW', 2)
863 C.addApproval('CRVW', 2)
864 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
865 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
866 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
867 self.waitUntilSettled()
868
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700869 self.gearman_server.release('.*-merge')
James E. Blairc6294a52012-08-17 10:19:48 -0700870 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700871 self.gearman_server.release('.*-merge')
James E. Blairc6294a52012-08-17 10:19:48 -0700872 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700873 self.gearman_server.release('.*-merge')
James E. Blairc6294a52012-08-17 10:19:48 -0700874 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -0700875 queue = self.gearman_server.getQueue()
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700876 ref = self.getParameter(queue[-1], 'ZUUL_REF')
877 self.gearman_server.hold_jobs_in_queue = False
878 self.gearman_server.release()
James E. Blairc6294a52012-08-17 10:19:48 -0700879 self.waitUntilSettled()
880
Monty Taylorbc758832013-06-17 17:22:42 -0400881 path = os.path.join(self.git_root, "org/project")
James E. Blairc6294a52012-08-17 10:19:48 -0700882 repo = git.Repo(path)
883 repo_messages = [c.message.strip() for c in repo.iter_commits(ref)]
884 repo_messages.reverse()
James E. Blairc6294a52012-08-17 10:19:48 -0700885 correct_messages = ['initial commit', 'mp commit', 'A-1', 'B-1', 'C-1']
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400886 self.assertEqual(repo_messages, correct_messages)
James E. Blairc6294a52012-08-17 10:19:48 -0700887
888 def test_build_configuration_branch_interaction(self):
889 "Test that switching between branches works"
890 self.test_build_configuration()
891 self.test_build_configuration_branch()
892 # C has been merged, undo that
Monty Taylorbc758832013-06-17 17:22:42 -0400893 path = os.path.join(self.upstream_root, "org/project")
James E. Blairc6294a52012-08-17 10:19:48 -0700894 repo = git.Repo(path)
895 repo.heads.master.commit = repo.commit('init')
896 self.test_build_configuration()
897
898 def test_build_configuration_multi_branch(self):
899 "Test that dependent changes on multiple branches are merged"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700900
901 self.gearman_server.hold_jobs_in_queue = True
James E. Blairc6294a52012-08-17 10:19:48 -0700902 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
903 B = self.fake_gerrit.addFakeChange('org/project', 'mp', 'B')
904 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
905 A.addApproval('CRVW', 2)
906 B.addApproval('CRVW', 2)
907 C.addApproval('CRVW', 2)
908 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
909 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
910 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
911 self.waitUntilSettled()
James E. Blairbb1fe502014-03-04 10:15:06 -0800912 queue = self.gearman_server.getQueue()
913 job_A = None
914 for job in queue:
915 if 'project-merge' in job.name:
916 job_A = job
917 ref_A = self.getParameter(job_A, 'ZUUL_REF')
918 commit_A = self.getParameter(job_A, 'ZUUL_COMMIT')
919 self.log.debug("Got Zuul ref for change A: %s" % ref_A)
920 self.log.debug("Got Zuul commit for change A: %s" % commit_A)
James E. Blairc6294a52012-08-17 10:19:48 -0700921
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700922 self.gearman_server.release('.*-merge')
James E. Blairc6294a52012-08-17 10:19:48 -0700923 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -0700924 queue = self.gearman_server.getQueue()
James E. Blaird320d7e2013-07-30 16:36:20 -0700925 job_B = None
926 for job in queue:
927 if 'project-merge' in job.name:
928 job_B = job
929 ref_B = self.getParameter(job_B, 'ZUUL_REF')
James E. Blairbb1fe502014-03-04 10:15:06 -0800930 commit_B = self.getParameter(job_B, 'ZUUL_COMMIT')
James E. Blairf750aa02013-07-15 14:11:24 -0700931 self.log.debug("Got Zuul ref for change B: %s" % ref_B)
James E. Blairbb1fe502014-03-04 10:15:06 -0800932 self.log.debug("Got Zuul commit for change B: %s" % commit_B)
933
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700934 self.gearman_server.release('.*-merge')
James E. Blairc6294a52012-08-17 10:19:48 -0700935 self.waitUntilSettled()
James E. Blair701c5b42013-06-06 09:34:59 -0700936 queue = self.gearman_server.getQueue()
James E. Blaird320d7e2013-07-30 16:36:20 -0700937 for job in queue:
938 if 'project-merge' in job.name:
939 job_C = job
940 ref_C = self.getParameter(job_C, 'ZUUL_REF')
James E. Blairbb1fe502014-03-04 10:15:06 -0800941 commit_C = self.getParameter(job_C, 'ZUUL_COMMIT')
James E. Blairf750aa02013-07-15 14:11:24 -0700942 self.log.debug("Got Zuul ref for change C: %s" % ref_C)
James E. Blairbb1fe502014-03-04 10:15:06 -0800943 self.log.debug("Got Zuul commit for change C: %s" % commit_C)
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700944 self.gearman_server.hold_jobs_in_queue = False
945 self.gearman_server.release()
James E. Blairc6294a52012-08-17 10:19:48 -0700946 self.waitUntilSettled()
947
Monty Taylorbc758832013-06-17 17:22:42 -0400948 path = os.path.join(self.git_root, "org/project")
James E. Blairc6294a52012-08-17 10:19:48 -0700949 repo = git.Repo(path)
950
951 repo_messages = [c.message.strip()
James E. Blairf750aa02013-07-15 14:11:24 -0700952 for c in repo.iter_commits(ref_C)]
James E. Blairbb1fe502014-03-04 10:15:06 -0800953 repo_shas = [c.hexsha for c in repo.iter_commits(ref_C)]
James E. Blairc6294a52012-08-17 10:19:48 -0700954 repo_messages.reverse()
James E. Blairc6294a52012-08-17 10:19:48 -0700955 correct_messages = ['initial commit', 'A-1', 'C-1']
James E. Blairbb1fe502014-03-04 10:15:06 -0800956 # Ensure the right commits are in the history for this ref
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400957 self.assertEqual(repo_messages, correct_messages)
James E. Blairbb1fe502014-03-04 10:15:06 -0800958 # Ensure ZUUL_REF -> ZUUL_COMMIT
959 self.assertEqual(repo_shas[0], commit_C)
James E. Blairc6294a52012-08-17 10:19:48 -0700960
961 repo_messages = [c.message.strip()
James E. Blairf750aa02013-07-15 14:11:24 -0700962 for c in repo.iter_commits(ref_B)]
James E. Blairbb1fe502014-03-04 10:15:06 -0800963 repo_shas = [c.hexsha for c in repo.iter_commits(ref_B)]
James E. Blairc6294a52012-08-17 10:19:48 -0700964 repo_messages.reverse()
James E. Blairc6294a52012-08-17 10:19:48 -0700965 correct_messages = ['initial commit', 'mp commit', 'B-1']
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400966 self.assertEqual(repo_messages, correct_messages)
James E. Blairbb1fe502014-03-04 10:15:06 -0800967 self.assertEqual(repo_shas[0], commit_B)
968
969 repo_messages = [c.message.strip()
970 for c in repo.iter_commits(ref_A)]
971 repo_shas = [c.hexsha for c in repo.iter_commits(ref_A)]
972 repo_messages.reverse()
973 correct_messages = ['initial commit', 'A-1']
974 self.assertEqual(repo_messages, correct_messages)
975 self.assertEqual(repo_shas[0], commit_A)
976
977 self.assertNotEqual(ref_A, ref_B, ref_C)
978 self.assertNotEqual(commit_A, commit_B, commit_C)
James E. Blair7f71c802012-08-22 13:04:32 -0700979
980 def test_one_job_project(self):
981 "Test that queueing works with one job"
982 A = self.fake_gerrit.addFakeChange('org/one-job-project',
983 'master', 'A')
984 B = self.fake_gerrit.addFakeChange('org/one-job-project',
985 'master', 'B')
986 A.addApproval('CRVW', 2)
987 B.addApproval('CRVW', 2)
988 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
989 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
990 self.waitUntilSettled()
991
Monty Taylor98f0f3e2013-07-06 16:02:31 -0400992 self.assertEqual(A.data['status'], 'MERGED')
993 self.assertEqual(A.reported, 2)
994 self.assertEqual(B.data['status'], 'MERGED')
995 self.assertEqual(B.reported, 2)
James E. Blaircaec0c52012-08-22 14:52:22 -0700996
Antoine Musso80edd5a2013-02-13 15:37:53 +0100997 def test_job_from_templates_launched(self):
998 "Test whether a job generated via a template can be launched"
James E. Blair1f4c2bb2013-04-26 08:40:46 -0700999
Antoine Musso80edd5a2013-02-13 15:37:53 +01001000 A = self.fake_gerrit.addFakeChange(
1001 'org/templated-project', 'master', 'A')
1002 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1003 self.waitUntilSettled()
Antoine Musso80edd5a2013-02-13 15:37:53 +01001004
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001005 self.assertEqual(self.getJobFromHistory('project-test1').result,
1006 'SUCCESS')
1007 self.assertEqual(self.getJobFromHistory('project-test2').result,
1008 'SUCCESS')
Antoine Musso80edd5a2013-02-13 15:37:53 +01001009
James E. Blair3e98c022013-12-16 15:25:38 -08001010 def test_layered_templates(self):
1011 "Test whether a job generated via a template can be launched"
1012
1013 A = self.fake_gerrit.addFakeChange(
1014 'org/layered-project', 'master', 'A')
1015 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1016 self.waitUntilSettled()
1017
1018 self.assertEqual(self.getJobFromHistory('project-test1').result,
1019 'SUCCESS')
1020 self.assertEqual(self.getJobFromHistory('project-test2').result,
1021 'SUCCESS')
James E. Blairaea6cf62013-12-16 15:38:12 -08001022 self.assertEqual(self.getJobFromHistory('layered-project-test3'
1023 ).result, 'SUCCESS')
1024 self.assertEqual(self.getJobFromHistory('layered-project-test4'
1025 ).result, 'SUCCESS')
James E. Blair12a92b12014-03-26 11:54:53 -07001026 self.assertEqual(self.getJobFromHistory('layered-project-foo-test5'
1027 ).result, 'SUCCESS')
James E. Blair3e98c022013-12-16 15:25:38 -08001028 self.assertEqual(self.getJobFromHistory('project-test6').result,
1029 'SUCCESS')
1030
James E. Blaircaec0c52012-08-22 14:52:22 -07001031 def test_dependent_changes_dequeue(self):
1032 "Test that dependent patches are not needlessly tested"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001033
James E. Blaircaec0c52012-08-22 14:52:22 -07001034 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1035 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1036 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1037 A.addApproval('CRVW', 2)
1038 B.addApproval('CRVW', 2)
1039 C.addApproval('CRVW', 2)
1040
1041 M1 = self.fake_gerrit.addFakeChange('org/project', 'master', 'M1')
1042 M1.setMerged()
1043
1044 # C -> B -> A -> M1
1045
1046 C.setDependsOn(B, 1)
1047 B.setDependsOn(A, 1)
1048 A.setDependsOn(M1, 1)
1049
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001050 self.worker.addFailTest('project-merge', A)
James E. Blaircaec0c52012-08-22 14:52:22 -07001051
1052 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1053 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1054 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1055
1056 self.waitUntilSettled()
1057
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001058 self.assertEqual(A.data['status'], 'NEW')
1059 self.assertEqual(A.reported, 2)
1060 self.assertEqual(B.data['status'], 'NEW')
1061 self.assertEqual(B.reported, 2)
1062 self.assertEqual(C.data['status'], 'NEW')
1063 self.assertEqual(C.reported, 2)
1064 self.assertEqual(len(self.history), 1)
James E. Blairec590122012-08-22 15:19:31 -07001065
James E. Blair972e3c72013-08-29 12:04:55 -07001066 def test_failing_dependent_changes(self):
1067 "Test that failing dependent patches are taken out of stream"
1068 self.worker.hold_jobs_in_build = True
1069 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1070 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1071 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1072 D = self.fake_gerrit.addFakeChange('org/project', 'master', 'D')
1073 E = self.fake_gerrit.addFakeChange('org/project', 'master', 'E')
1074 A.addApproval('CRVW', 2)
1075 B.addApproval('CRVW', 2)
1076 C.addApproval('CRVW', 2)
1077 D.addApproval('CRVW', 2)
1078 E.addApproval('CRVW', 2)
1079
1080 # E, D -> C -> B, A
1081
1082 D.setDependsOn(C, 1)
1083 C.setDependsOn(B, 1)
1084
1085 self.worker.addFailTest('project-test1', B)
1086
1087 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1088 self.fake_gerrit.addEvent(D.addApproval('APRV', 1))
1089 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1090 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1091 self.fake_gerrit.addEvent(E.addApproval('APRV', 1))
1092
1093 self.waitUntilSettled()
1094 self.worker.release('.*-merge')
1095 self.waitUntilSettled()
1096 self.worker.release('.*-merge')
1097 self.waitUntilSettled()
1098 self.worker.release('.*-merge')
1099 self.waitUntilSettled()
1100 self.worker.release('.*-merge')
1101 self.waitUntilSettled()
1102 self.worker.release('.*-merge')
1103 self.waitUntilSettled()
1104
1105 self.worker.hold_jobs_in_build = False
1106 for build in self.builds:
1107 if build.parameters['ZUUL_CHANGE'] != '1':
1108 build.release()
1109 self.waitUntilSettled()
1110
1111 self.worker.release()
1112 self.waitUntilSettled()
1113
1114 self.assertEqual(A.data['status'], 'MERGED')
1115 self.assertEqual(A.reported, 2)
Jeremy Stanley10837132014-08-02 16:10:56 +00001116 self.assertIn('Build succeeded', A.messages[1])
James E. Blair972e3c72013-08-29 12:04:55 -07001117 self.assertEqual(B.data['status'], 'NEW')
1118 self.assertEqual(B.reported, 2)
Jeremy Stanley10837132014-08-02 16:10:56 +00001119 self.assertIn('Build failed', B.messages[1])
James E. Blair972e3c72013-08-29 12:04:55 -07001120 self.assertEqual(C.data['status'], 'NEW')
1121 self.assertEqual(C.reported, 2)
Jeremy Stanley10837132014-08-02 16:10:56 +00001122 self.assertIn('depends on a change', C.messages[1])
James E. Blair972e3c72013-08-29 12:04:55 -07001123 self.assertEqual(D.data['status'], 'NEW')
1124 self.assertEqual(D.reported, 2)
Jeremy Stanley10837132014-08-02 16:10:56 +00001125 self.assertIn('depends on a change', D.messages[1])
James E. Blair972e3c72013-08-29 12:04:55 -07001126 self.assertEqual(E.data['status'], 'MERGED')
1127 self.assertEqual(E.reported, 2)
Jeremy Stanley10837132014-08-02 16:10:56 +00001128 self.assertIn('Build succeeded', E.messages[1])
James E. Blair972e3c72013-08-29 12:04:55 -07001129 self.assertEqual(len(self.history), 18)
1130
James E. Blairec590122012-08-22 15:19:31 -07001131 def test_head_is_dequeued_once(self):
James E. Blair2fa50962013-01-30 21:50:41 -08001132 "Test that if a change at the head fails it is dequeued only once"
James E. Blairec590122012-08-22 15:19:31 -07001133 # If it's dequeued more than once, we should see extra
1134 # aborted jobs.
James E. Blairec590122012-08-22 15:19:31 -07001135
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001136 self.worker.hold_jobs_in_build = True
James E. Blairec590122012-08-22 15:19:31 -07001137 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
1138 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
1139 C = self.fake_gerrit.addFakeChange('org/project1', 'master', 'C')
1140 A.addApproval('CRVW', 2)
1141 B.addApproval('CRVW', 2)
1142 C.addApproval('CRVW', 2)
1143
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001144 self.worker.addFailTest('project1-test1', A)
1145 self.worker.addFailTest('project1-test2', A)
1146 self.worker.addFailTest('project1-project2-integration', A)
James E. Blairec590122012-08-22 15:19:31 -07001147
1148 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1149 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1150 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1151
1152 self.waitUntilSettled()
James E. Blairec590122012-08-22 15:19:31 -07001153
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001154 self.assertEqual(len(self.builds), 1)
1155 self.assertEqual(self.builds[0].name, 'project1-merge')
1156 self.assertTrue(self.job_has_changes(self.builds[0], A))
James E. Blairec590122012-08-22 15:19:31 -07001157
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001158 self.worker.release('.*-merge')
James E. Blairec590122012-08-22 15:19:31 -07001159 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001160 self.worker.release('.*-merge')
James E. Blairec590122012-08-22 15:19:31 -07001161 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001162 self.worker.release('.*-merge')
James E. Blairec590122012-08-22 15:19:31 -07001163 self.waitUntilSettled()
1164
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001165 self.assertEqual(len(self.builds), 9)
1166 self.assertEqual(self.builds[0].name, 'project1-test1')
1167 self.assertEqual(self.builds[1].name, 'project1-test2')
1168 self.assertEqual(self.builds[2].name, 'project1-project2-integration')
1169 self.assertEqual(self.builds[3].name, 'project1-test1')
1170 self.assertEqual(self.builds[4].name, 'project1-test2')
1171 self.assertEqual(self.builds[5].name, 'project1-project2-integration')
1172 self.assertEqual(self.builds[6].name, 'project1-test1')
1173 self.assertEqual(self.builds[7].name, 'project1-test2')
1174 self.assertEqual(self.builds[8].name, 'project1-project2-integration')
James E. Blairec590122012-08-22 15:19:31 -07001175
Monty Taylor6bef8ef2013-06-02 08:17:12 -04001176 self.release(self.builds[0])
James E. Blairec590122012-08-22 15:19:31 -07001177 self.waitUntilSettled()
1178
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001179 self.assertEqual(len(self.builds), 3) # test2,integration, merge for B
1180 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 6)
James E. Blairec590122012-08-22 15:19:31 -07001181
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001182 self.worker.hold_jobs_in_build = False
1183 self.worker.release()
James E. Blairec590122012-08-22 15:19:31 -07001184 self.waitUntilSettled()
1185
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001186 self.assertEqual(len(self.builds), 0)
1187 self.assertEqual(len(self.history), 20)
James E. Blaircaec0c52012-08-22 14:52:22 -07001188
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001189 self.assertEqual(A.data['status'], 'NEW')
1190 self.assertEqual(B.data['status'], 'MERGED')
1191 self.assertEqual(C.data['status'], 'MERGED')
1192 self.assertEqual(A.reported, 2)
1193 self.assertEqual(B.reported, 2)
1194 self.assertEqual(C.reported, 2)
James E. Blair4ec821f2012-08-23 15:28:28 -07001195
1196 def test_nonvoting_job(self):
1197 "Test that non-voting jobs don't vote."
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001198
James E. Blair4ec821f2012-08-23 15:28:28 -07001199 A = self.fake_gerrit.addFakeChange('org/nonvoting-project',
1200 'master', 'A')
1201 A.addApproval('CRVW', 2)
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001202 self.worker.addFailTest('nonvoting-project-test2', A)
James E. Blair4ec821f2012-08-23 15:28:28 -07001203 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1204
1205 self.waitUntilSettled()
James E. Blair4ec821f2012-08-23 15:28:28 -07001206
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001207 self.assertEqual(A.data['status'], 'MERGED')
1208 self.assertEqual(A.reported, 2)
1209 self.assertEqual(
1210 self.getJobFromHistory('nonvoting-project-merge').result,
1211 'SUCCESS')
1212 self.assertEqual(
1213 self.getJobFromHistory('nonvoting-project-test1').result,
1214 'SUCCESS')
1215 self.assertEqual(
1216 self.getJobFromHistory('nonvoting-project-test2').result,
1217 'FAILURE')
James E. Blaire0487072012-08-29 17:38:31 -07001218
1219 def test_check_queue_success(self):
1220 "Test successful check queue jobs."
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001221
James E. Blaire0487072012-08-29 17:38:31 -07001222 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1223 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1224
1225 self.waitUntilSettled()
James E. Blaire0487072012-08-29 17:38:31 -07001226
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001227 self.assertEqual(A.data['status'], 'NEW')
1228 self.assertEqual(A.reported, 1)
1229 self.assertEqual(self.getJobFromHistory('project-merge').result,
1230 'SUCCESS')
1231 self.assertEqual(self.getJobFromHistory('project-test1').result,
1232 'SUCCESS')
1233 self.assertEqual(self.getJobFromHistory('project-test2').result,
1234 'SUCCESS')
James E. Blaire0487072012-08-29 17:38:31 -07001235
1236 def test_check_queue_failure(self):
1237 "Test failed check queue jobs."
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001238
James E. Blaire0487072012-08-29 17:38:31 -07001239 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001240 self.worker.addFailTest('project-test2', A)
James E. Blaire0487072012-08-29 17:38:31 -07001241 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1242
1243 self.waitUntilSettled()
James E. Blaire0487072012-08-29 17:38:31 -07001244
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001245 self.assertEqual(A.data['status'], 'NEW')
1246 self.assertEqual(A.reported, 1)
1247 self.assertEqual(self.getJobFromHistory('project-merge').result,
James E. Blair78e31b32013-07-09 09:11:34 -07001248 'SUCCESS')
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001249 self.assertEqual(self.getJobFromHistory('project-test1').result,
1250 'SUCCESS')
1251 self.assertEqual(self.getJobFromHistory('project-test2').result,
1252 'FAILURE')
James E. Blair127bc182012-08-28 15:55:15 -07001253
1254 def test_dependent_behind_dequeue(self):
1255 "test that dependent changes behind dequeued changes work"
1256 # This complicated test is a reproduction of a real life bug
1257 self.sched.reconfigure(self.config)
James E. Blair127bc182012-08-28 15:55:15 -07001258
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001259 self.worker.hold_jobs_in_build = True
James E. Blair127bc182012-08-28 15:55:15 -07001260 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
1261 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
1262 C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
1263 D = self.fake_gerrit.addFakeChange('org/project2', 'master', 'D')
1264 E = self.fake_gerrit.addFakeChange('org/project2', 'master', 'E')
1265 F = self.fake_gerrit.addFakeChange('org/project3', 'master', 'F')
1266 D.setDependsOn(C, 1)
1267 E.setDependsOn(D, 1)
1268 A.addApproval('CRVW', 2)
1269 B.addApproval('CRVW', 2)
1270 C.addApproval('CRVW', 2)
1271 D.addApproval('CRVW', 2)
1272 E.addApproval('CRVW', 2)
1273 F.addApproval('CRVW', 2)
1274
1275 A.fail_merge = True
James E. Blair127bc182012-08-28 15:55:15 -07001276
1277 # Change object re-use in the gerrit trigger is hidden if
1278 # changes are added in quick succession; waiting makes it more
1279 # like real life.
1280 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1281 self.waitUntilSettled()
1282 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1283 self.waitUntilSettled()
1284
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001285 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001286 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001287 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001288 self.waitUntilSettled()
1289
1290 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1291 self.waitUntilSettled()
1292 self.fake_gerrit.addEvent(D.addApproval('APRV', 1))
1293 self.waitUntilSettled()
1294 self.fake_gerrit.addEvent(E.addApproval('APRV', 1))
1295 self.waitUntilSettled()
1296 self.fake_gerrit.addEvent(F.addApproval('APRV', 1))
1297 self.waitUntilSettled()
1298
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001299 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001300 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001301 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001302 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001303 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001304 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001305 self.worker.release('.*-merge')
James E. Blair127bc182012-08-28 15:55:15 -07001306 self.waitUntilSettled()
1307
1308 # all jobs running
James E. Blaire955e062012-10-08 09:49:03 -07001309
1310 # Grab pointers to the jobs we want to release before
1311 # releasing any, because list indexes may change as
1312 # the jobs complete.
Monty Taylor6bef8ef2013-06-02 08:17:12 -04001313 a, b, c = self.builds[:3]
James E. Blaire955e062012-10-08 09:49:03 -07001314 a.release()
1315 b.release()
1316 c.release()
James E. Blair127bc182012-08-28 15:55:15 -07001317 self.waitUntilSettled()
1318
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001319 self.worker.hold_jobs_in_build = False
1320 self.worker.release()
James E. Blair127bc182012-08-28 15:55:15 -07001321 self.waitUntilSettled()
1322
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001323 self.assertEqual(A.data['status'], 'NEW')
1324 self.assertEqual(B.data['status'], 'MERGED')
1325 self.assertEqual(C.data['status'], 'MERGED')
1326 self.assertEqual(D.data['status'], 'MERGED')
1327 self.assertEqual(E.data['status'], 'MERGED')
1328 self.assertEqual(F.data['status'], 'MERGED')
James E. Blair127bc182012-08-28 15:55:15 -07001329
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001330 self.assertEqual(A.reported, 2)
1331 self.assertEqual(B.reported, 2)
1332 self.assertEqual(C.reported, 2)
1333 self.assertEqual(D.reported, 2)
1334 self.assertEqual(E.reported, 2)
1335 self.assertEqual(F.reported, 2)
James E. Blair127bc182012-08-28 15:55:15 -07001336
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001337 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 15)
1338 self.assertEqual(len(self.history), 44)
James E. Blair05fed602012-09-07 12:45:24 -07001339
1340 def test_merger_repack(self):
1341 "Test that the merger works after a repack"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001342
James E. Blair05fed602012-09-07 12:45:24 -07001343 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1344 A.addApproval('CRVW', 2)
1345 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1346 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001347 self.assertEqual(self.getJobFromHistory('project-merge').result,
1348 'SUCCESS')
1349 self.assertEqual(self.getJobFromHistory('project-test1').result,
1350 'SUCCESS')
1351 self.assertEqual(self.getJobFromHistory('project-test2').result,
1352 'SUCCESS')
1353 self.assertEqual(A.data['status'], 'MERGED')
1354 self.assertEqual(A.reported, 2)
James E. Blair05fed602012-09-07 12:45:24 -07001355 self.assertEmptyQueues()
James E. Blair4ca985f2013-05-30 12:27:43 -07001356 self.worker.build_history = []
James E. Blair05fed602012-09-07 12:45:24 -07001357
Monty Taylorbc758832013-06-17 17:22:42 -04001358 path = os.path.join(self.git_root, "org/project")
1359 print repack_repo(path)
James E. Blair05fed602012-09-07 12:45:24 -07001360
1361 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1362 A.addApproval('CRVW', 2)
1363 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1364 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001365 self.assertEqual(self.getJobFromHistory('project-merge').result,
1366 'SUCCESS')
1367 self.assertEqual(self.getJobFromHistory('project-test1').result,
1368 'SUCCESS')
1369 self.assertEqual(self.getJobFromHistory('project-test2').result,
1370 'SUCCESS')
1371 self.assertEqual(A.data['status'], 'MERGED')
1372 self.assertEqual(A.reported, 2)
James E. Blair7ee88a22012-09-12 18:59:31 +02001373
James E. Blair4886f282012-11-15 09:27:33 -08001374 def test_merger_repack_large_change(self):
1375 "Test that the merger works with large changes after a repack"
1376 # https://bugs.launchpad.net/zuul/+bug/1078946
James E. Blairac2c3242014-01-24 13:38:51 -08001377 # This test assumes the repo is already cloned; make sure it is
1378 url = self.sched.triggers['gerrit'].getGitUrl(
1379 self.sched.layout.projects['org/project1'])
James E. Blair4076e2b2014-01-28 12:42:20 -08001380 self.merge_server.merger.addProject('org/project1', url)
James E. Blair4886f282012-11-15 09:27:33 -08001381 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
1382 A.addPatchset(large=True)
Monty Taylorbc758832013-06-17 17:22:42 -04001383 path = os.path.join(self.upstream_root, "org/project1")
1384 print repack_repo(path)
1385 path = os.path.join(self.git_root, "org/project1")
1386 print repack_repo(path)
James E. Blair4886f282012-11-15 09:27:33 -08001387
1388 A.addApproval('CRVW', 2)
1389 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1390 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001391 self.assertEqual(self.getJobFromHistory('project1-merge').result,
1392 'SUCCESS')
1393 self.assertEqual(self.getJobFromHistory('project1-test1').result,
1394 'SUCCESS')
1395 self.assertEqual(self.getJobFromHistory('project1-test2').result,
1396 'SUCCESS')
1397 self.assertEqual(A.data['status'], 'MERGED')
1398 self.assertEqual(A.reported, 2)
James E. Blair4886f282012-11-15 09:27:33 -08001399
James E. Blair7ee88a22012-09-12 18:59:31 +02001400 def test_nonexistent_job(self):
1401 "Test launching a job that doesn't exist"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001402 # Set to the state immediately after a restart
1403 self.resetGearmanServer()
1404 self.launcher.negative_function_cache_ttl = 0
James E. Blair7ee88a22012-09-12 18:59:31 +02001405
1406 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1407 A.addApproval('CRVW', 2)
1408 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1409 # There may be a thread about to report a lost change
1410 while A.reported < 2:
1411 self.waitUntilSettled()
Monty Taylor6bef8ef2013-06-02 08:17:12 -04001412 job_names = [x.name for x in self.history]
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001413 self.assertFalse(job_names)
1414 self.assertEqual(A.data['status'], 'NEW')
1415 self.assertEqual(A.reported, 2)
James E. Blair7ee88a22012-09-12 18:59:31 +02001416 self.assertEmptyQueues()
1417
1418 # Make sure things still work:
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001419 self.registerJobs()
James E. Blair7ee88a22012-09-12 18:59:31 +02001420 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1421 A.addApproval('CRVW', 2)
1422 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1423 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001424 self.assertEqual(self.getJobFromHistory('project-merge').result,
1425 'SUCCESS')
1426 self.assertEqual(self.getJobFromHistory('project-test1').result,
1427 'SUCCESS')
1428 self.assertEqual(self.getJobFromHistory('project-test2').result,
1429 'SUCCESS')
1430 self.assertEqual(A.data['status'], 'MERGED')
1431 self.assertEqual(A.reported, 2)
James E. Blairf62d4282012-12-31 17:01:50 -08001432
1433 def test_single_nonexistent_post_job(self):
1434 "Test launching a single post job that doesn't exist"
James E. Blairf62d4282012-12-31 17:01:50 -08001435 e = {
1436 "type": "ref-updated",
1437 "submitter": {
1438 "name": "User Name",
1439 },
1440 "refUpdate": {
1441 "oldRev": "90f173846e3af9154517b88543ffbd1691f31366",
1442 "newRev": "d479a0bfcb34da57a31adb2a595c0cf687812543",
1443 "refName": "master",
1444 "project": "org/project",
1445 }
1446 }
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001447 # Set to the state immediately after a restart
1448 self.resetGearmanServer()
1449 self.launcher.negative_function_cache_ttl = 0
1450
James E. Blairf62d4282012-12-31 17:01:50 -08001451 self.fake_gerrit.addEvent(e)
1452 self.waitUntilSettled()
1453
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001454 self.assertEqual(len(self.history), 0)
James E. Blair2fa50962013-01-30 21:50:41 -08001455
1456 def test_new_patchset_dequeues_old(self):
1457 "Test that a new patchset causes the old to be dequeued"
1458 # D -> C (depends on B) -> B (depends on A) -> A -> M
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001459 self.worker.hold_jobs_in_build = True
James E. Blair2fa50962013-01-30 21:50:41 -08001460 M = self.fake_gerrit.addFakeChange('org/project', 'master', 'M')
1461 M.setMerged()
1462
1463 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1464 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1465 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1466 D = self.fake_gerrit.addFakeChange('org/project', 'master', 'D')
1467 A.addApproval('CRVW', 2)
1468 B.addApproval('CRVW', 2)
1469 C.addApproval('CRVW', 2)
1470 D.addApproval('CRVW', 2)
1471
1472 C.setDependsOn(B, 1)
1473 B.setDependsOn(A, 1)
1474 A.setDependsOn(M, 1)
1475
1476 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1477 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1478 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1479 self.fake_gerrit.addEvent(D.addApproval('APRV', 1))
1480 self.waitUntilSettled()
1481
1482 B.addPatchset()
1483 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(2))
1484 self.waitUntilSettled()
1485
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001486 self.worker.hold_jobs_in_build = False
1487 self.worker.release()
James E. Blair2fa50962013-01-30 21:50:41 -08001488 self.waitUntilSettled()
1489
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001490 self.assertEqual(A.data['status'], 'MERGED')
1491 self.assertEqual(A.reported, 2)
1492 self.assertEqual(B.data['status'], 'NEW')
1493 self.assertEqual(B.reported, 2)
1494 self.assertEqual(C.data['status'], 'NEW')
1495 self.assertEqual(C.reported, 2)
1496 self.assertEqual(D.data['status'], 'MERGED')
1497 self.assertEqual(D.reported, 2)
1498 self.assertEqual(len(self.history), 9) # 3 each for A, B, D.
James E. Blair2fa50962013-01-30 21:50:41 -08001499
James E. Blairba437362015-02-07 11:41:52 -08001500 def test_new_patchset_check(self):
1501 "Test a new patchset in check"
Antoine Mussobd86a312014-01-08 14:51:33 +01001502
1503 self.worker.hold_jobs_in_build = True
1504
1505 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
James E. Blairba437362015-02-07 11:41:52 -08001506 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1507 check_pipeline = self.sched.layout.pipelines['check']
1508
1509 # Add two git-dependent changes
1510 B.setDependsOn(A, 1)
1511 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1512 self.waitUntilSettled()
Antoine Mussobd86a312014-01-08 14:51:33 +01001513 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1514 self.waitUntilSettled()
James E. Blairba437362015-02-07 11:41:52 -08001515
1516 # A live item, and a non-live/live pair
1517 items = check_pipeline.getAllItems()
1518 self.assertEqual(len(items), 3)
1519
1520 self.assertEqual(items[0].change.number, '1')
1521 self.assertEqual(items[0].change.patchset, '1')
1522 self.assertFalse(items[0].live)
1523
1524 self.assertEqual(items[1].change.number, '2')
1525 self.assertEqual(items[1].change.patchset, '1')
1526 self.assertTrue(items[1].live)
1527
1528 self.assertEqual(items[2].change.number, '1')
1529 self.assertEqual(items[2].change.patchset, '1')
1530 self.assertTrue(items[2].live)
1531
1532 # Add a new patchset to A
1533 A.addPatchset()
1534 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
1535 self.waitUntilSettled()
1536
1537 # The live copy of A,1 should be gone, but the non-live and B
1538 # should continue, and we should have a new A,2
1539 items = check_pipeline.getAllItems()
1540 self.assertEqual(len(items), 3)
1541
1542 self.assertEqual(items[0].change.number, '1')
1543 self.assertEqual(items[0].change.patchset, '1')
1544 self.assertFalse(items[0].live)
1545
1546 self.assertEqual(items[1].change.number, '2')
1547 self.assertEqual(items[1].change.patchset, '1')
1548 self.assertTrue(items[1].live)
1549
1550 self.assertEqual(items[2].change.number, '1')
1551 self.assertEqual(items[2].change.patchset, '2')
1552 self.assertTrue(items[2].live)
1553
1554 # Add a new patchset to B
1555 B.addPatchset()
1556 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(2))
1557 self.waitUntilSettled()
1558
1559 # The live copy of B,1 should be gone, and it's non-live copy of A,1
1560 # but we should have a new B,2 (still based on A,1)
1561 items = check_pipeline.getAllItems()
1562 self.assertEqual(len(items), 3)
1563
1564 self.assertEqual(items[0].change.number, '1')
1565 self.assertEqual(items[0].change.patchset, '2')
1566 self.assertTrue(items[0].live)
1567
1568 self.assertEqual(items[1].change.number, '1')
1569 self.assertEqual(items[1].change.patchset, '1')
1570 self.assertFalse(items[1].live)
1571
1572 self.assertEqual(items[2].change.number, '2')
1573 self.assertEqual(items[2].change.patchset, '2')
1574 self.assertTrue(items[2].live)
1575
1576 self.builds[0].release()
1577 self.waitUntilSettled()
1578 self.builds[0].release()
1579 self.waitUntilSettled()
1580 self.worker.hold_jobs_in_build = False
1581 self.worker.release()
1582 self.waitUntilSettled()
1583
1584 self.assertEqual(A.reported, 1)
1585 self.assertEqual(B.reported, 1)
1586 self.assertEqual(self.history[0].result, 'ABORTED')
1587 self.assertEqual(self.history[0].changes, '1,1')
1588 self.assertEqual(self.history[1].result, 'ABORTED')
1589 self.assertEqual(self.history[1].changes, '1,1 2,1')
1590 self.assertEqual(self.history[2].result, 'SUCCESS')
1591 self.assertEqual(self.history[2].changes, '1,2')
1592 self.assertEqual(self.history[3].result, 'SUCCESS')
1593 self.assertEqual(self.history[3].changes, '1,1 2,2')
1594
1595 def test_abandoned_gate(self):
1596 "Test that an abandoned change is dequeued from gate"
1597
1598 self.worker.hold_jobs_in_build = True
1599
1600 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1601 A.addApproval('CRVW', 2)
1602 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1603 self.waitUntilSettled()
Antoine Mussobd86a312014-01-08 14:51:33 +01001604 self.assertEqual(len(self.builds), 1, "One job being built (on hold)")
1605 self.assertEqual(self.builds[0].name, 'project-merge')
1606
1607 self.fake_gerrit.addEvent(A.getChangeAbandonedEvent())
1608 self.waitUntilSettled()
1609
Antoine Mussobd86a312014-01-08 14:51:33 +01001610 self.worker.release('.*-merge')
1611 self.waitUntilSettled()
1612
1613 self.assertEqual(len(self.builds), 0, "No job running")
Antoine Mussobd86a312014-01-08 14:51:33 +01001614 self.assertEqual(len(self.history), 1, "Only one build in history")
1615 self.assertEqual(self.history[0].result, 'ABORTED',
James E. Blairba437362015-02-07 11:41:52 -08001616 "Build should have been aborted")
1617 self.assertEqual(A.reported, 1,
1618 "Abandoned gate change should report only start")
1619
1620 def test_abandoned_check(self):
1621 "Test that an abandoned change is dequeued from check"
1622
1623 self.worker.hold_jobs_in_build = True
1624
1625 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1626 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1627 check_pipeline = self.sched.layout.pipelines['check']
1628
1629 # Add two git-dependent changes
1630 B.setDependsOn(A, 1)
1631 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1632 self.waitUntilSettled()
1633 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1634 self.waitUntilSettled()
1635 # A live item, and a non-live/live pair
1636 items = check_pipeline.getAllItems()
1637 self.assertEqual(len(items), 3)
1638
1639 self.assertEqual(items[0].change.number, '1')
1640 self.assertFalse(items[0].live)
1641
1642 self.assertEqual(items[1].change.number, '2')
1643 self.assertTrue(items[1].live)
1644
1645 self.assertEqual(items[2].change.number, '1')
1646 self.assertTrue(items[2].live)
1647
1648 # Abandon A
1649 self.fake_gerrit.addEvent(A.getChangeAbandonedEvent())
1650 self.waitUntilSettled()
1651
1652 # The live copy of A should be gone, but the non-live and B
1653 # should continue
1654 items = check_pipeline.getAllItems()
1655 self.assertEqual(len(items), 2)
1656
1657 self.assertEqual(items[0].change.number, '1')
1658 self.assertFalse(items[0].live)
1659
1660 self.assertEqual(items[1].change.number, '2')
1661 self.assertTrue(items[1].live)
1662
1663 self.worker.hold_jobs_in_build = False
1664 self.worker.release()
1665 self.waitUntilSettled()
1666
1667 self.assertEqual(len(self.history), 4)
1668 self.assertEqual(self.history[0].result, 'ABORTED',
Antoine Mussobd86a312014-01-08 14:51:33 +01001669 'Build should have been aborted')
1670 self.assertEqual(A.reported, 0, "Abandoned change should not report")
James E. Blairba437362015-02-07 11:41:52 -08001671 self.assertEqual(B.reported, 1, "Change should report")
Antoine Mussobd86a312014-01-08 14:51:33 +01001672
Arx Cruzb1b010d2013-10-28 19:49:59 -02001673 def test_zuul_url_return(self):
1674 "Test if ZUUL_URL is returning when zuul_url is set in zuul.conf"
James E. Blair4076e2b2014-01-28 12:42:20 -08001675 self.assertTrue(self.sched.config.has_option('merger', 'zuul_url'))
Arx Cruzb1b010d2013-10-28 19:49:59 -02001676 self.worker.hold_jobs_in_build = True
1677
1678 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1679 A.addApproval('CRVW', 2)
1680 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1681 self.waitUntilSettled()
1682
1683 self.assertEqual(len(self.builds), 1)
1684 for build in self.builds:
1685 self.assertTrue('ZUUL_URL' in build.parameters)
1686
1687 self.worker.hold_jobs_in_build = False
1688 self.worker.release()
1689 self.waitUntilSettled()
1690
James E. Blair2fa50962013-01-30 21:50:41 -08001691 def test_new_patchset_dequeues_old_on_head(self):
1692 "Test that a new patchset causes the old to be dequeued (at head)"
1693 # D -> C (depends on B) -> B (depends on A) -> A -> M
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001694 self.worker.hold_jobs_in_build = True
James E. Blair2fa50962013-01-30 21:50:41 -08001695 M = self.fake_gerrit.addFakeChange('org/project', 'master', 'M')
1696 M.setMerged()
1697 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1698 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1699 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1700 D = self.fake_gerrit.addFakeChange('org/project', 'master', 'D')
1701 A.addApproval('CRVW', 2)
1702 B.addApproval('CRVW', 2)
1703 C.addApproval('CRVW', 2)
1704 D.addApproval('CRVW', 2)
1705
1706 C.setDependsOn(B, 1)
1707 B.setDependsOn(A, 1)
1708 A.setDependsOn(M, 1)
1709
1710 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1711 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1712 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1713 self.fake_gerrit.addEvent(D.addApproval('APRV', 1))
1714 self.waitUntilSettled()
1715
1716 A.addPatchset()
1717 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
1718 self.waitUntilSettled()
1719
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001720 self.worker.hold_jobs_in_build = False
1721 self.worker.release()
James E. Blair2fa50962013-01-30 21:50:41 -08001722 self.waitUntilSettled()
1723
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001724 self.assertEqual(A.data['status'], 'NEW')
1725 self.assertEqual(A.reported, 2)
1726 self.assertEqual(B.data['status'], 'NEW')
1727 self.assertEqual(B.reported, 2)
1728 self.assertEqual(C.data['status'], 'NEW')
1729 self.assertEqual(C.reported, 2)
1730 self.assertEqual(D.data['status'], 'MERGED')
1731 self.assertEqual(D.reported, 2)
1732 self.assertEqual(len(self.history), 7)
James E. Blair2fa50962013-01-30 21:50:41 -08001733
1734 def test_new_patchset_dequeues_old_without_dependents(self):
1735 "Test that a new patchset causes only the old to be dequeued"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001736 self.worker.hold_jobs_in_build = True
James E. Blair2fa50962013-01-30 21:50:41 -08001737 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1738 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1739 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1740 A.addApproval('CRVW', 2)
1741 B.addApproval('CRVW', 2)
1742 C.addApproval('CRVW', 2)
1743
1744 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1745 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1746 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1747 self.waitUntilSettled()
1748
1749 B.addPatchset()
1750 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(2))
1751 self.waitUntilSettled()
1752
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001753 self.worker.hold_jobs_in_build = False
1754 self.worker.release()
James E. Blair2fa50962013-01-30 21:50:41 -08001755 self.waitUntilSettled()
1756
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001757 self.assertEqual(A.data['status'], 'MERGED')
1758 self.assertEqual(A.reported, 2)
1759 self.assertEqual(B.data['status'], 'NEW')
1760 self.assertEqual(B.reported, 2)
1761 self.assertEqual(C.data['status'], 'MERGED')
1762 self.assertEqual(C.reported, 2)
1763 self.assertEqual(len(self.history), 9)
James E. Blair2fa50962013-01-30 21:50:41 -08001764
1765 def test_new_patchset_dequeues_old_independent_queue(self):
1766 "Test that a new patchset causes the old to be dequeued (independent)"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001767 self.worker.hold_jobs_in_build = True
James E. Blair2fa50962013-01-30 21:50:41 -08001768 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1769 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1770 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1771 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1772 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1773 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
1774 self.waitUntilSettled()
1775
1776 B.addPatchset()
1777 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(2))
1778 self.waitUntilSettled()
1779
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001780 self.worker.hold_jobs_in_build = False
1781 self.worker.release()
James E. Blair2fa50962013-01-30 21:50:41 -08001782 self.waitUntilSettled()
1783
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001784 self.assertEqual(A.data['status'], 'NEW')
1785 self.assertEqual(A.reported, 1)
1786 self.assertEqual(B.data['status'], 'NEW')
1787 self.assertEqual(B.reported, 1)
1788 self.assertEqual(C.data['status'], 'NEW')
1789 self.assertEqual(C.reported, 1)
1790 self.assertEqual(len(self.history), 10)
1791 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 1)
James E. Blair7d0dedc2013-02-21 17:26:09 -08001792
James E. Blair18c64442014-03-18 10:14:45 -07001793 def test_noop_job(self):
1794 "Test that the internal noop job works"
1795 A = self.fake_gerrit.addFakeChange('org/noop-project', 'master', 'A')
1796 A.addApproval('CRVW', 2)
1797 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1798 self.waitUntilSettled()
1799
1800 self.assertEqual(len(self.gearman_server.getQueue()), 0)
1801 self.assertTrue(self.sched._areAllBuildsComplete())
1802 self.assertEqual(len(self.history), 0)
1803 self.assertEqual(A.data['status'], 'MERGED')
1804 self.assertEqual(A.reported, 2)
1805
James E. Blair7d0dedc2013-02-21 17:26:09 -08001806 def test_zuul_refs(self):
1807 "Test that zuul refs exist and have the right changes"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001808 self.worker.hold_jobs_in_build = True
James E. Blair7d0dedc2013-02-21 17:26:09 -08001809 M1 = self.fake_gerrit.addFakeChange('org/project1', 'master', 'M1')
1810 M1.setMerged()
1811 M2 = self.fake_gerrit.addFakeChange('org/project2', 'master', 'M2')
1812 M2.setMerged()
1813
1814 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
1815 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
1816 C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
1817 D = self.fake_gerrit.addFakeChange('org/project2', 'master', 'D')
1818 A.addApproval('CRVW', 2)
1819 B.addApproval('CRVW', 2)
1820 C.addApproval('CRVW', 2)
1821 D.addApproval('CRVW', 2)
1822 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1823 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1824 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1825 self.fake_gerrit.addEvent(D.addApproval('APRV', 1))
1826
1827 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001828 self.worker.release('.*-merge')
James E. Blair7d0dedc2013-02-21 17:26:09 -08001829 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001830 self.worker.release('.*-merge')
James E. Blair7d0dedc2013-02-21 17:26:09 -08001831 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001832 self.worker.release('.*-merge')
James E. Blair7d0dedc2013-02-21 17:26:09 -08001833 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001834 self.worker.release('.*-merge')
James E. Blair7d0dedc2013-02-21 17:26:09 -08001835 self.waitUntilSettled()
1836
James E. Blair7d0dedc2013-02-21 17:26:09 -08001837 a_zref = b_zref = c_zref = d_zref = None
Monty Taylor6bef8ef2013-06-02 08:17:12 -04001838 for x in self.builds:
James E. Blair7d0dedc2013-02-21 17:26:09 -08001839 if x.parameters['ZUUL_CHANGE'] == '3':
1840 a_zref = x.parameters['ZUUL_REF']
1841 if x.parameters['ZUUL_CHANGE'] == '4':
1842 b_zref = x.parameters['ZUUL_REF']
1843 if x.parameters['ZUUL_CHANGE'] == '5':
1844 c_zref = x.parameters['ZUUL_REF']
1845 if x.parameters['ZUUL_CHANGE'] == '6':
1846 d_zref = x.parameters['ZUUL_REF']
1847
1848 # There are... four... refs.
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001849 self.assertIsNotNone(a_zref)
1850 self.assertIsNotNone(b_zref)
1851 self.assertIsNotNone(c_zref)
1852 self.assertIsNotNone(d_zref)
James E. Blair7d0dedc2013-02-21 17:26:09 -08001853
1854 # And they should all be different
1855 refs = set([a_zref, b_zref, c_zref, d_zref])
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001856 self.assertEqual(len(refs), 4)
James E. Blair7d0dedc2013-02-21 17:26:09 -08001857
1858 # a ref should have a, not b, and should not be in project2
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001859 self.assertTrue(self.ref_has_change(a_zref, A))
1860 self.assertFalse(self.ref_has_change(a_zref, B))
1861 self.assertFalse(self.ref_has_change(a_zref, M2))
James E. Blair7d0dedc2013-02-21 17:26:09 -08001862
1863 # b ref should have a and b, and should not be in project2
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001864 self.assertTrue(self.ref_has_change(b_zref, A))
1865 self.assertTrue(self.ref_has_change(b_zref, B))
1866 self.assertFalse(self.ref_has_change(b_zref, M2))
James E. Blair7d0dedc2013-02-21 17:26:09 -08001867
1868 # c ref should have a and b in 1, c in 2
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001869 self.assertTrue(self.ref_has_change(c_zref, A))
1870 self.assertTrue(self.ref_has_change(c_zref, B))
1871 self.assertTrue(self.ref_has_change(c_zref, C))
1872 self.assertFalse(self.ref_has_change(c_zref, D))
James E. Blair7d0dedc2013-02-21 17:26:09 -08001873
1874 # d ref should have a and b in 1, c and d in 2
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001875 self.assertTrue(self.ref_has_change(d_zref, A))
1876 self.assertTrue(self.ref_has_change(d_zref, B))
1877 self.assertTrue(self.ref_has_change(d_zref, C))
1878 self.assertTrue(self.ref_has_change(d_zref, D))
James E. Blair7d0dedc2013-02-21 17:26:09 -08001879
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001880 self.worker.hold_jobs_in_build = False
1881 self.worker.release()
James E. Blair7d0dedc2013-02-21 17:26:09 -08001882 self.waitUntilSettled()
1883
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001884 self.assertEqual(A.data['status'], 'MERGED')
1885 self.assertEqual(A.reported, 2)
1886 self.assertEqual(B.data['status'], 'MERGED')
1887 self.assertEqual(B.reported, 2)
1888 self.assertEqual(C.data['status'], 'MERGED')
1889 self.assertEqual(C.reported, 2)
1890 self.assertEqual(D.data['status'], 'MERGED')
1891 self.assertEqual(D.reported, 2)
James E. Blair70c71582013-03-06 08:50:50 -08001892
James E. Blair4a28a882013-08-23 15:17:33 -07001893 def test_rerun_on_error(self):
1894 "Test that if a worker fails to run a job, it is run again"
1895 self.worker.hold_jobs_in_build = True
1896 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1897 A.addApproval('CRVW', 2)
1898 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1899 self.waitUntilSettled()
1900
1901 self.builds[0].run_error = True
1902 self.worker.hold_jobs_in_build = False
1903 self.worker.release()
1904 self.waitUntilSettled()
1905 self.assertEqual(self.countJobResults(self.history, 'RUN_ERROR'), 1)
1906 self.assertEqual(self.countJobResults(self.history, 'SUCCESS'), 3)
1907
James E. Blair412e5582013-04-22 15:50:12 -07001908 def test_statsd(self):
1909 "Test each of the statsd methods used in the scheduler"
1910 import extras
1911 statsd = extras.try_import('statsd.statsd')
1912 statsd.incr('test-incr')
1913 statsd.timing('test-timing', 3)
Alex Gaynor813d39b2014-05-17 16:17:16 -07001914 statsd.gauge('test-gauge', 12)
James E. Blair412e5582013-04-22 15:50:12 -07001915 self.assertReportedStat('test-incr', '1|c')
1916 self.assertReportedStat('test-timing', '3|ms')
Alex Gaynor813d39b2014-05-17 16:17:16 -07001917 self.assertReportedStat('test-gauge', '12|g')
James E. Blair412e5582013-04-22 15:50:12 -07001918
James E. Blairdad52252014-02-07 16:59:17 -08001919 def test_stuck_job_cleanup(self):
1920 "Test that pending jobs are cleaned up if removed from layout"
James E. Blair18c64442014-03-18 10:14:45 -07001921 # This job won't be registered at startup because it is not in
1922 # the standard layout, but we need it to already be registerd
1923 # for when we reconfigure, as that is when Zuul will attempt
1924 # to run the new job.
1925 self.worker.registerFunction('build:gate-noop')
James E. Blairdad52252014-02-07 16:59:17 -08001926 self.gearman_server.hold_jobs_in_queue = True
1927 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1928 A.addApproval('CRVW', 2)
1929 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1930 self.waitUntilSettled()
1931 self.assertEqual(len(self.gearman_server.getQueue()), 1)
1932
1933 self.config.set('zuul', 'layout_config',
1934 'tests/fixtures/layout-no-jobs.yaml')
1935 self.sched.reconfigure(self.config)
1936 self.waitUntilSettled()
1937
James E. Blair18c64442014-03-18 10:14:45 -07001938 self.gearman_server.release('gate-noop')
James E. Blairdad52252014-02-07 16:59:17 -08001939 self.waitUntilSettled()
1940 self.assertEqual(len(self.gearman_server.getQueue()), 0)
1941 self.assertTrue(self.sched._areAllBuildsComplete())
1942
1943 self.assertEqual(len(self.history), 1)
James E. Blair18c64442014-03-18 10:14:45 -07001944 self.assertEqual(self.history[0].name, 'gate-noop')
James E. Blairdad52252014-02-07 16:59:17 -08001945 self.assertEqual(self.history[0].result, 'SUCCESS')
1946
James E. Blair70c71582013-03-06 08:50:50 -08001947 def test_file_jobs(self):
1948 "Test that file jobs run only when appropriate"
1949 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1950 A.addPatchset(['pip-requires'])
1951 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1952 A.addApproval('CRVW', 2)
1953 B.addApproval('CRVW', 2)
1954 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1955 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1956 self.waitUntilSettled()
1957
Monty Taylor6bef8ef2013-06-02 08:17:12 -04001958 testfile_jobs = [x for x in self.history
James E. Blair70c71582013-03-06 08:50:50 -08001959 if x.name == 'project-testfile']
1960
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001961 self.assertEqual(len(testfile_jobs), 1)
1962 self.assertEqual(testfile_jobs[0].changes, '1,2')
1963 self.assertEqual(A.data['status'], 'MERGED')
1964 self.assertEqual(A.reported, 2)
1965 self.assertEqual(B.data['status'], 'MERGED')
1966 self.assertEqual(B.reported, 2)
James E. Blair3c5e5b52013-04-26 11:17:03 -07001967
1968 def test_test_config(self):
1969 "Test that we can test the config"
1970 sched = zuul.scheduler.Scheduler()
James E. Blair6c358e72013-07-29 17:06:47 -07001971 sched.registerTrigger(None, 'gerrit')
James E. Blair63bb0ef2013-07-29 17:14:51 -07001972 sched.registerTrigger(None, 'timer')
James E. Blairc494d542014-08-06 09:23:52 -07001973 sched.registerTrigger(None, 'zuul')
Clark Boylanb640e052014-04-03 16:41:46 -07001974 sched.testConfig(self.config.get('zuul', 'layout_config'))
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001975
1976 def test_build_description(self):
1977 "Test that build descriptions update"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001978 self.worker.registerFunction('set_description:' +
1979 self.worker.worker_id)
1980
1981 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1982 A.addApproval('CRVW', 2)
1983 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1984 self.waitUntilSettled()
Monty Taylor6bef8ef2013-06-02 08:17:12 -04001985 desc = self.history[0].description
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001986 self.log.debug("Description: %s" % desc)
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001987 self.assertTrue(re.search("Branch.*master", desc))
1988 self.assertTrue(re.search("Pipeline.*gate", desc))
1989 self.assertTrue(re.search("project-merge.*SUCCESS", desc))
1990 self.assertTrue(re.search("project-test1.*SUCCESS", desc))
1991 self.assertTrue(re.search("project-test2.*SUCCESS", desc))
1992 self.assertTrue(re.search("Reported result.*SUCCESS", desc))
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001993
James E. Blairc8a1e052014-02-25 09:29:26 -08001994 def test_queue_names(self):
1995 "Test shared change queue names"
1996 project1 = self.sched.layout.projects['org/project1']
1997 project2 = self.sched.layout.projects['org/project2']
1998 q1 = self.sched.layout.pipelines['gate'].getQueue(project1)
1999 q2 = self.sched.layout.pipelines['gate'].getQueue(project2)
2000 self.assertEqual(q1.name, 'integration')
2001 self.assertEqual(q2.name, 'integration')
2002
2003 self.config.set('zuul', 'layout_config',
2004 'tests/fixtures/layout-bad-queue.yaml')
2005 with testtools.ExpectedException(
2006 Exception, "More than one name assigned to change queue"):
2007 self.sched.reconfigure(self.config)
2008
James E. Blair64ed6f22013-07-10 14:07:23 -07002009 def test_queue_precedence(self):
2010 "Test that queue precedence works"
2011
2012 self.gearman_server.hold_jobs_in_queue = True
James E. Blair8de58bd2013-07-18 16:23:33 -07002013 self.worker.hold_jobs_in_build = True
James E. Blair64ed6f22013-07-10 14:07:23 -07002014 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2015 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2016 A.addApproval('CRVW', 2)
2017 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2018
2019 self.waitUntilSettled()
2020 self.gearman_server.hold_jobs_in_queue = False
2021 self.gearman_server.release()
2022 self.waitUntilSettled()
2023
James E. Blair8de58bd2013-07-18 16:23:33 -07002024 # Run one build at a time to ensure non-race order:
2025 for x in range(6):
2026 self.release(self.builds[0])
2027 self.waitUntilSettled()
2028 self.worker.hold_jobs_in_build = False
2029 self.waitUntilSettled()
2030
James E. Blair64ed6f22013-07-10 14:07:23 -07002031 self.log.debug(self.history)
2032 self.assertEqual(self.history[0].pipeline, 'gate')
2033 self.assertEqual(self.history[1].pipeline, 'check')
2034 self.assertEqual(self.history[2].pipeline, 'gate')
2035 self.assertEqual(self.history[3].pipeline, 'gate')
2036 self.assertEqual(self.history[4].pipeline, 'check')
2037 self.assertEqual(self.history[5].pipeline, 'check')
2038
Clark Boylana5edbe42014-06-03 16:39:10 -07002039 def test_json_status(self):
James E. Blair1843a552013-07-03 14:19:52 -07002040 "Test that we can retrieve JSON status info"
2041 self.worker.hold_jobs_in_build = True
2042 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2043 A.addApproval('CRVW', 2)
2044 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2045 self.waitUntilSettled()
2046
2047 port = self.webapp.server.socket.getsockname()[1]
2048
Yuriy Taradaya6d452f2014-04-16 12:36:20 +04002049 req = urllib2.Request("http://localhost:%s/status.json" % port)
Yuriy Taradaya6d452f2014-04-16 12:36:20 +04002050 f = urllib2.urlopen(req)
Clark Boylanaa4f2e72014-06-03 21:22:40 -07002051 headers = f.info()
2052 self.assertIn('Content-Length', headers)
2053 self.assertIn('Content-Type', headers)
2054 self.assertEqual(headers['Content-Type'],
2055 'application/json; charset=UTF-8')
2056 self.assertIn('Last-Modified', headers)
James E. Blair1843a552013-07-03 14:19:52 -07002057 data = f.read()
2058
2059 self.worker.hold_jobs_in_build = False
2060 self.worker.release()
2061 self.waitUntilSettled()
2062
2063 data = json.loads(data)
2064 status_jobs = set()
2065 for p in data['pipelines']:
2066 for q in p['change_queues']:
James E. Blairbfb8e042014-12-30 17:01:44 -08002067 if p['name'] in ['gate', 'conflict']:
Clark Boylanaf2476f2014-01-23 14:47:36 -08002068 self.assertEqual(q['window'], 20)
2069 else:
2070 self.assertEqual(q['window'], 0)
James E. Blair1843a552013-07-03 14:19:52 -07002071 for head in q['heads']:
2072 for change in head:
Clark Boylanaf2476f2014-01-23 14:47:36 -08002073 self.assertTrue(change['active'])
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002074 self.assertEqual(change['id'], '1,1')
James E. Blair1843a552013-07-03 14:19:52 -07002075 for job in change['jobs']:
2076 status_jobs.add(job['name'])
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002077 self.assertIn('project-merge', status_jobs)
2078 self.assertIn('project-test1', status_jobs)
2079 self.assertIn('project-test2', status_jobs)
James E. Blair1843a552013-07-03 14:19:52 -07002080
James E. Blairc3d428e2013-12-03 15:06:48 -08002081 def test_merging_queues(self):
2082 "Test that transitively-connected change queues are merged"
2083 self.config.set('zuul', 'layout_config',
2084 'tests/fixtures/layout-merge-queues.yaml')
2085 self.sched.reconfigure(self.config)
2086 self.assertEqual(len(self.sched.layout.pipelines['gate'].queues), 1)
2087
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002088 def test_node_label(self):
2089 "Test that a job runs on a specific node label"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07002090 self.worker.registerFunction('build:node-project-test1:debian')
2091
2092 A = self.fake_gerrit.addFakeChange('org/node-project', 'master', 'A')
2093 A.addApproval('CRVW', 2)
2094 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2095 self.waitUntilSettled()
James E. Blair4ca985f2013-05-30 12:27:43 -07002096
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002097 self.assertIsNone(self.getJobFromHistory('node-project-merge').node)
2098 self.assertEqual(self.getJobFromHistory('node-project-test1').node,
2099 'debian')
2100 self.assertIsNone(self.getJobFromHistory('node-project-test2').node)
James E. Blaircdccd972013-07-01 12:10:22 -07002101
2102 def test_live_reconfiguration(self):
2103 "Test that live reconfiguration works"
2104 self.worker.hold_jobs_in_build = True
2105 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2106 A.addApproval('CRVW', 2)
2107 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2108 self.waitUntilSettled()
2109
2110 self.sched.reconfigure(self.config)
2111
2112 self.worker.hold_jobs_in_build = False
2113 self.worker.release()
2114 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -04002115 self.assertEqual(self.getJobFromHistory('project-merge').result,
2116 'SUCCESS')
2117 self.assertEqual(self.getJobFromHistory('project-test1').result,
2118 'SUCCESS')
2119 self.assertEqual(self.getJobFromHistory('project-test2').result,
2120 'SUCCESS')
2121 self.assertEqual(A.data['status'], 'MERGED')
2122 self.assertEqual(A.reported, 2)
James E. Blair287c06d2013-07-24 10:39:30 -07002123
James E. Blaire712d9f2013-07-31 11:40:11 -07002124 def test_live_reconfiguration_functions(self):
2125 "Test live reconfiguration with a custom function"
2126 self.worker.registerFunction('build:node-project-test1:debian')
2127 self.worker.registerFunction('build:node-project-test1:wheezy')
2128 A = self.fake_gerrit.addFakeChange('org/node-project', 'master', 'A')
2129 A.addApproval('CRVW', 2)
2130 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2131 self.waitUntilSettled()
2132
2133 self.assertIsNone(self.getJobFromHistory('node-project-merge').node)
2134 self.assertEqual(self.getJobFromHistory('node-project-test1').node,
2135 'debian')
2136 self.assertIsNone(self.getJobFromHistory('node-project-test2').node)
2137
2138 self.config.set('zuul', 'layout_config',
2139 'tests/fixtures/layout-live-'
2140 'reconfiguration-functions.yaml')
2141 self.sched.reconfigure(self.config)
2142 self.worker.build_history = []
2143
2144 B = self.fake_gerrit.addFakeChange('org/node-project', 'master', 'B')
2145 B.addApproval('CRVW', 2)
2146 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2147 self.waitUntilSettled()
2148
2149 self.assertIsNone(self.getJobFromHistory('node-project-merge').node)
2150 self.assertEqual(self.getJobFromHistory('node-project-test1').node,
2151 'wheezy')
2152 self.assertIsNone(self.getJobFromHistory('node-project-test2').node)
2153
James E. Blair287c06d2013-07-24 10:39:30 -07002154 def test_delayed_repo_init(self):
2155 self.config.set('zuul', 'layout_config',
2156 'tests/fixtures/layout-delayed-repo-init.yaml')
2157 self.sched.reconfigure(self.config)
2158
2159 self.init_repo("org/new-project")
2160 A = self.fake_gerrit.addFakeChange('org/new-project', 'master', 'A')
2161
2162 A.addApproval('CRVW', 2)
2163 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2164 self.waitUntilSettled()
2165 self.assertEqual(self.getJobFromHistory('project-merge').result,
2166 'SUCCESS')
2167 self.assertEqual(self.getJobFromHistory('project-test1').result,
2168 'SUCCESS')
2169 self.assertEqual(self.getJobFromHistory('project-test2').result,
2170 'SUCCESS')
2171 self.assertEqual(A.data['status'], 'MERGED')
2172 self.assertEqual(A.reported, 2)
James E. Blair63bb0ef2013-07-29 17:14:51 -07002173
Clark Boylan6dbbc482013-10-18 10:57:31 -07002174 def test_repo_deleted(self):
2175 self.config.set('zuul', 'layout_config',
2176 'tests/fixtures/layout-repo-deleted.yaml')
2177 self.sched.reconfigure(self.config)
2178
2179 self.init_repo("org/delete-project")
2180 A = self.fake_gerrit.addFakeChange('org/delete-project', 'master', 'A')
2181
2182 A.addApproval('CRVW', 2)
2183 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2184 self.waitUntilSettled()
2185 self.assertEqual(self.getJobFromHistory('project-merge').result,
2186 'SUCCESS')
2187 self.assertEqual(self.getJobFromHistory('project-test1').result,
2188 'SUCCESS')
2189 self.assertEqual(self.getJobFromHistory('project-test2').result,
2190 'SUCCESS')
2191 self.assertEqual(A.data['status'], 'MERGED')
2192 self.assertEqual(A.reported, 2)
2193
2194 # Delete org/new-project zuul repo. Should be recloned.
2195 shutil.rmtree(os.path.join(self.git_root, "org/delete-project"))
2196
2197 B = self.fake_gerrit.addFakeChange('org/delete-project', 'master', 'B')
2198
2199 B.addApproval('CRVW', 2)
2200 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2201 self.waitUntilSettled()
2202 self.assertEqual(self.getJobFromHistory('project-merge').result,
2203 'SUCCESS')
2204 self.assertEqual(self.getJobFromHistory('project-test1').result,
2205 'SUCCESS')
2206 self.assertEqual(self.getJobFromHistory('project-test2').result,
2207 'SUCCESS')
2208 self.assertEqual(B.data['status'], 'MERGED')
2209 self.assertEqual(B.reported, 2)
2210
James E. Blair63bb0ef2013-07-29 17:14:51 -07002211 def test_timer(self):
2212 "Test that a periodic job is triggered"
2213 self.worker.hold_jobs_in_build = True
2214 self.config.set('zuul', 'layout_config',
2215 'tests/fixtures/layout-timer.yaml')
2216 self.sched.reconfigure(self.config)
2217 self.registerJobs()
2218
Clark Boylan3ee090a2014-04-03 20:55:09 -07002219 # The pipeline triggers every second, so we should have seen
2220 # several by now.
2221 time.sleep(5)
James E. Blair63bb0ef2013-07-29 17:14:51 -07002222 self.waitUntilSettled()
Clark Boylan3ee090a2014-04-03 20:55:09 -07002223
2224 self.assertEqual(len(self.builds), 2)
2225
James E. Blair63bb0ef2013-07-29 17:14:51 -07002226 port = self.webapp.server.socket.getsockname()[1]
2227
2228 f = urllib.urlopen("http://localhost:%s/status.json" % port)
2229 data = f.read()
2230
2231 self.worker.hold_jobs_in_build = False
Clark Boylan3ee090a2014-04-03 20:55:09 -07002232 # Stop queuing timer triggered jobs so that the assertions
2233 # below don't race against more jobs being queued.
2234 self.config.set('zuul', 'layout_config',
2235 'tests/fixtures/layout-no-timer.yaml')
2236 self.sched.reconfigure(self.config)
2237 self.registerJobs()
James E. Blair63bb0ef2013-07-29 17:14:51 -07002238 self.worker.release()
2239 self.waitUntilSettled()
2240
2241 self.assertEqual(self.getJobFromHistory(
2242 'project-bitrot-stable-old').result, 'SUCCESS')
2243 self.assertEqual(self.getJobFromHistory(
2244 'project-bitrot-stable-older').result, 'SUCCESS')
2245
2246 data = json.loads(data)
2247 status_jobs = set()
2248 for p in data['pipelines']:
2249 for q in p['change_queues']:
2250 for head in q['heads']:
2251 for change in head:
Alex Gaynorddb9ef32013-09-16 21:04:58 -07002252 self.assertEqual(change['id'], None)
James E. Blair63bb0ef2013-07-29 17:14:51 -07002253 for job in change['jobs']:
2254 status_jobs.add(job['name'])
2255 self.assertIn('project-bitrot-stable-old', status_jobs)
2256 self.assertIn('project-bitrot-stable-older', status_jobs)
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002257
James E. Blair4f6033c2014-03-27 15:49:09 -07002258 def test_idle(self):
2259 "Test that frequent periodic jobs work"
2260 self.worker.hold_jobs_in_build = True
James E. Blair4f6033c2014-03-27 15:49:09 -07002261
Clark Boylan3ee090a2014-04-03 20:55:09 -07002262 for x in range(1, 3):
2263 # Test that timer triggers periodic jobs even across
2264 # layout config reloads.
2265 # Start timer trigger
2266 self.config.set('zuul', 'layout_config',
2267 'tests/fixtures/layout-idle.yaml')
2268 self.sched.reconfigure(self.config)
2269 self.registerJobs()
James E. Blair4f6033c2014-03-27 15:49:09 -07002270
Clark Boylan3ee090a2014-04-03 20:55:09 -07002271 # The pipeline triggers every second, so we should have seen
2272 # several by now.
2273 time.sleep(5)
2274 self.waitUntilSettled()
2275
2276 # Stop queuing timer triggered jobs so that the assertions
2277 # below don't race against more jobs being queued.
2278 self.config.set('zuul', 'layout_config',
2279 'tests/fixtures/layout-no-timer.yaml')
2280 self.sched.reconfigure(self.config)
2281 self.registerJobs()
2282
2283 self.assertEqual(len(self.builds), 2)
2284 self.worker.release('.*')
2285 self.waitUntilSettled()
2286 self.assertEqual(len(self.builds), 0)
2287 self.assertEqual(len(self.history), x * 2)
James E. Blair4f6033c2014-03-27 15:49:09 -07002288
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002289 def test_check_smtp_pool(self):
2290 self.config.set('zuul', 'layout_config',
2291 'tests/fixtures/layout-smtp.yaml')
2292 self.sched.reconfigure(self.config)
2293
2294 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2295 self.waitUntilSettled()
2296
2297 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2298 self.waitUntilSettled()
2299
James E. Blairff80a2f2013-12-27 13:24:06 -08002300 self.assertEqual(len(self.smtp_messages), 2)
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002301
2302 # A.messages only holds what FakeGerrit places in it. Thus we
2303 # work on the knowledge of what the first message should be as
2304 # it is only configured to go to SMTP.
2305
2306 self.assertEqual('zuul@example.com',
James E. Blairff80a2f2013-12-27 13:24:06 -08002307 self.smtp_messages[0]['from_email'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002308 self.assertEqual(['you@example.com'],
James E. Blairff80a2f2013-12-27 13:24:06 -08002309 self.smtp_messages[0]['to_email'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002310 self.assertEqual('Starting check jobs.',
James E. Blairff80a2f2013-12-27 13:24:06 -08002311 self.smtp_messages[0]['body'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002312
2313 self.assertEqual('zuul_from@example.com',
James E. Blairff80a2f2013-12-27 13:24:06 -08002314 self.smtp_messages[1]['from_email'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002315 self.assertEqual(['alternative_me@example.com'],
James E. Blairff80a2f2013-12-27 13:24:06 -08002316 self.smtp_messages[1]['to_email'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002317 self.assertEqual(A.messages[0],
James E. Blairff80a2f2013-12-27 13:24:06 -08002318 self.smtp_messages[1]['body'])
James E. Blairad28e912013-11-27 10:43:22 -08002319
James E. Blaire5910202013-12-27 09:50:31 -08002320 def test_timer_smtp(self):
2321 "Test that a periodic job is triggered"
Clark Boylan3ee090a2014-04-03 20:55:09 -07002322 self.worker.hold_jobs_in_build = True
James E. Blaire5910202013-12-27 09:50:31 -08002323 self.config.set('zuul', 'layout_config',
2324 'tests/fixtures/layout-timer-smtp.yaml')
2325 self.sched.reconfigure(self.config)
2326 self.registerJobs()
2327
Clark Boylan3ee090a2014-04-03 20:55:09 -07002328 # The pipeline triggers every second, so we should have seen
2329 # several by now.
2330 time.sleep(5)
James E. Blaire5910202013-12-27 09:50:31 -08002331 self.waitUntilSettled()
2332
Clark Boylan3ee090a2014-04-03 20:55:09 -07002333 self.assertEqual(len(self.builds), 2)
2334 self.worker.release('.*')
2335 self.waitUntilSettled()
2336 self.assertEqual(len(self.history), 2)
2337
James E. Blaire5910202013-12-27 09:50:31 -08002338 self.assertEqual(self.getJobFromHistory(
2339 'project-bitrot-stable-old').result, 'SUCCESS')
2340 self.assertEqual(self.getJobFromHistory(
2341 'project-bitrot-stable-older').result, 'SUCCESS')
2342
James E. Blairff80a2f2013-12-27 13:24:06 -08002343 self.assertEqual(len(self.smtp_messages), 1)
James E. Blaire5910202013-12-27 09:50:31 -08002344
2345 # A.messages only holds what FakeGerrit places in it. Thus we
2346 # work on the knowledge of what the first message should be as
2347 # it is only configured to go to SMTP.
2348
2349 self.assertEqual('zuul_from@example.com',
James E. Blairff80a2f2013-12-27 13:24:06 -08002350 self.smtp_messages[0]['from_email'])
James E. Blaire5910202013-12-27 09:50:31 -08002351 self.assertEqual(['alternative_me@example.com'],
James E. Blairff80a2f2013-12-27 13:24:06 -08002352 self.smtp_messages[0]['to_email'])
James E. Blaire5910202013-12-27 09:50:31 -08002353 self.assertIn('Subject: Periodic check for org/project succeeded',
James E. Blairff80a2f2013-12-27 13:24:06 -08002354 self.smtp_messages[0]['headers'])
James E. Blaire5910202013-12-27 09:50:31 -08002355
Clark Boylan3ee090a2014-04-03 20:55:09 -07002356 # Stop queuing timer triggered jobs and let any that may have
2357 # queued through so that end of test assertions pass.
2358 self.config.set('zuul', 'layout_config',
2359 'tests/fixtures/layout-no-timer.yaml')
2360 self.sched.reconfigure(self.config)
2361 self.registerJobs()
James E. Blairf8058972014-08-15 16:09:16 -07002362 self.waitUntilSettled()
Clark Boylan3ee090a2014-04-03 20:55:09 -07002363 self.worker.release('.*')
2364 self.waitUntilSettled()
2365
James E. Blairad28e912013-11-27 10:43:22 -08002366 def test_client_enqueue(self):
2367 "Test that the RPC client can enqueue a change"
2368 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2369 A.addApproval('CRVW', 2)
2370 A.addApproval('APRV', 1)
2371
2372 client = zuul.rpcclient.RPCClient('127.0.0.1',
2373 self.gearman_server.port)
2374 r = client.enqueue(pipeline='gate',
2375 project='org/project',
2376 trigger='gerrit',
James E. Blair36658cf2013-12-06 17:53:48 -08002377 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08002378 self.waitUntilSettled()
2379 self.assertEqual(self.getJobFromHistory('project-merge').result,
2380 'SUCCESS')
2381 self.assertEqual(self.getJobFromHistory('project-test1').result,
2382 'SUCCESS')
2383 self.assertEqual(self.getJobFromHistory('project-test2').result,
2384 'SUCCESS')
2385 self.assertEqual(A.data['status'], 'MERGED')
2386 self.assertEqual(A.reported, 2)
2387 self.assertEqual(r, True)
2388
2389 def test_client_enqueue_negative(self):
2390 "Test that the RPC client returns errors"
2391 client = zuul.rpcclient.RPCClient('127.0.0.1',
2392 self.gearman_server.port)
2393 with testtools.ExpectedException(zuul.rpcclient.RPCFailure,
2394 "Invalid project"):
2395 r = client.enqueue(pipeline='gate',
2396 project='project-does-not-exist',
2397 trigger='gerrit',
James E. Blair36658cf2013-12-06 17:53:48 -08002398 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08002399 client.shutdown()
2400 self.assertEqual(r, False)
2401
2402 with testtools.ExpectedException(zuul.rpcclient.RPCFailure,
2403 "Invalid pipeline"):
2404 r = client.enqueue(pipeline='pipeline-does-not-exist',
2405 project='org/project',
2406 trigger='gerrit',
James E. Blair36658cf2013-12-06 17:53:48 -08002407 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08002408 client.shutdown()
2409 self.assertEqual(r, False)
2410
2411 with testtools.ExpectedException(zuul.rpcclient.RPCFailure,
2412 "Invalid trigger"):
2413 r = client.enqueue(pipeline='gate',
2414 project='org/project',
2415 trigger='trigger-does-not-exist',
James E. Blair36658cf2013-12-06 17:53:48 -08002416 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08002417 client.shutdown()
2418 self.assertEqual(r, False)
2419
2420 with testtools.ExpectedException(zuul.rpcclient.RPCFailure,
2421 "Invalid change"):
2422 r = client.enqueue(pipeline='gate',
2423 project='org/project',
2424 trigger='gerrit',
James E. Blair36658cf2013-12-06 17:53:48 -08002425 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08002426 client.shutdown()
2427 self.assertEqual(r, False)
2428
2429 self.waitUntilSettled()
2430 self.assertEqual(len(self.history), 0)
2431 self.assertEqual(len(self.builds), 0)
James E. Blair36658cf2013-12-06 17:53:48 -08002432
2433 def test_client_promote(self):
2434 "Test that the RPC client can promote a change"
2435 self.worker.hold_jobs_in_build = True
2436 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2437 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2438 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
2439 A.addApproval('CRVW', 2)
2440 B.addApproval('CRVW', 2)
2441 C.addApproval('CRVW', 2)
2442
2443 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2444 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2445 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
2446
2447 self.waitUntilSettled()
2448
Sean Daguef39b9ca2014-01-10 21:34:35 -05002449 items = self.sched.layout.pipelines['gate'].getAllItems()
2450 enqueue_times = {}
2451 for item in items:
2452 enqueue_times[str(item.change)] = item.enqueue_time
2453
James E. Blair36658cf2013-12-06 17:53:48 -08002454 client = zuul.rpcclient.RPCClient('127.0.0.1',
2455 self.gearman_server.port)
2456 r = client.promote(pipeline='gate',
2457 change_ids=['2,1', '3,1'])
2458
Sean Daguef39b9ca2014-01-10 21:34:35 -05002459 # ensure that enqueue times are durable
2460 items = self.sched.layout.pipelines['gate'].getAllItems()
2461 for item in items:
2462 self.assertEqual(
2463 enqueue_times[str(item.change)], item.enqueue_time)
2464
James E. Blair78acec92014-02-06 07:11:32 -08002465 self.waitUntilSettled()
James E. Blair36658cf2013-12-06 17:53:48 -08002466 self.worker.release('.*-merge')
2467 self.waitUntilSettled()
2468 self.worker.release('.*-merge')
2469 self.waitUntilSettled()
2470 self.worker.release('.*-merge')
2471 self.waitUntilSettled()
2472
2473 self.assertEqual(len(self.builds), 6)
2474 self.assertEqual(self.builds[0].name, 'project-test1')
2475 self.assertEqual(self.builds[1].name, 'project-test2')
2476 self.assertEqual(self.builds[2].name, 'project-test1')
2477 self.assertEqual(self.builds[3].name, 'project-test2')
2478 self.assertEqual(self.builds[4].name, 'project-test1')
2479 self.assertEqual(self.builds[5].name, 'project-test2')
2480
2481 self.assertTrue(self.job_has_changes(self.builds[0], B))
2482 self.assertFalse(self.job_has_changes(self.builds[0], A))
2483 self.assertFalse(self.job_has_changes(self.builds[0], C))
2484
2485 self.assertTrue(self.job_has_changes(self.builds[2], B))
2486 self.assertTrue(self.job_has_changes(self.builds[2], C))
2487 self.assertFalse(self.job_has_changes(self.builds[2], A))
2488
2489 self.assertTrue(self.job_has_changes(self.builds[4], B))
2490 self.assertTrue(self.job_has_changes(self.builds[4], C))
2491 self.assertTrue(self.job_has_changes(self.builds[4], A))
2492
2493 self.worker.release()
2494 self.waitUntilSettled()
2495
2496 self.assertEqual(A.data['status'], 'MERGED')
2497 self.assertEqual(A.reported, 2)
2498 self.assertEqual(B.data['status'], 'MERGED')
2499 self.assertEqual(B.reported, 2)
2500 self.assertEqual(C.data['status'], 'MERGED')
2501 self.assertEqual(C.reported, 2)
2502
2503 client.shutdown()
2504 self.assertEqual(r, True)
2505
2506 def test_client_promote_dependent(self):
2507 "Test that the RPC client can promote a dependent change"
2508 # C (depends on B) -> B -> A ; then promote C to get:
2509 # A -> C (depends on B) -> B
2510 self.worker.hold_jobs_in_build = True
2511 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2512 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2513 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
2514
2515 C.setDependsOn(B, 1)
2516
2517 A.addApproval('CRVW', 2)
2518 B.addApproval('CRVW', 2)
2519 C.addApproval('CRVW', 2)
2520
2521 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2522 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2523 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
2524
2525 self.waitUntilSettled()
2526
2527 client = zuul.rpcclient.RPCClient('127.0.0.1',
2528 self.gearman_server.port)
2529 r = client.promote(pipeline='gate',
2530 change_ids=['3,1'])
2531
James E. Blair78acec92014-02-06 07:11:32 -08002532 self.waitUntilSettled()
James E. Blair36658cf2013-12-06 17:53:48 -08002533 self.worker.release('.*-merge')
2534 self.waitUntilSettled()
2535 self.worker.release('.*-merge')
2536 self.waitUntilSettled()
2537 self.worker.release('.*-merge')
2538 self.waitUntilSettled()
2539
2540 self.assertEqual(len(self.builds), 6)
2541 self.assertEqual(self.builds[0].name, 'project-test1')
2542 self.assertEqual(self.builds[1].name, 'project-test2')
2543 self.assertEqual(self.builds[2].name, 'project-test1')
2544 self.assertEqual(self.builds[3].name, 'project-test2')
2545 self.assertEqual(self.builds[4].name, 'project-test1')
2546 self.assertEqual(self.builds[5].name, 'project-test2')
2547
2548 self.assertTrue(self.job_has_changes(self.builds[0], B))
2549 self.assertFalse(self.job_has_changes(self.builds[0], A))
2550 self.assertFalse(self.job_has_changes(self.builds[0], C))
2551
2552 self.assertTrue(self.job_has_changes(self.builds[2], B))
2553 self.assertTrue(self.job_has_changes(self.builds[2], C))
2554 self.assertFalse(self.job_has_changes(self.builds[2], A))
2555
2556 self.assertTrue(self.job_has_changes(self.builds[4], B))
2557 self.assertTrue(self.job_has_changes(self.builds[4], C))
2558 self.assertTrue(self.job_has_changes(self.builds[4], A))
2559
2560 self.worker.release()
2561 self.waitUntilSettled()
2562
2563 self.assertEqual(A.data['status'], 'MERGED')
2564 self.assertEqual(A.reported, 2)
2565 self.assertEqual(B.data['status'], 'MERGED')
2566 self.assertEqual(B.reported, 2)
2567 self.assertEqual(C.data['status'], 'MERGED')
2568 self.assertEqual(C.reported, 2)
2569
2570 client.shutdown()
2571 self.assertEqual(r, True)
2572
2573 def test_client_promote_negative(self):
2574 "Test that the RPC client returns errors for promotion"
2575 self.worker.hold_jobs_in_build = True
2576 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2577 A.addApproval('CRVW', 2)
2578 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2579 self.waitUntilSettled()
2580
2581 client = zuul.rpcclient.RPCClient('127.0.0.1',
2582 self.gearman_server.port)
2583
2584 with testtools.ExpectedException(zuul.rpcclient.RPCFailure):
2585 r = client.promote(pipeline='nonexistent',
2586 change_ids=['2,1', '3,1'])
2587 client.shutdown()
2588 self.assertEqual(r, False)
2589
2590 with testtools.ExpectedException(zuul.rpcclient.RPCFailure):
2591 r = client.promote(pipeline='gate',
2592 change_ids=['4,1'])
2593 client.shutdown()
2594 self.assertEqual(r, False)
2595
2596 self.worker.hold_jobs_in_build = False
2597 self.worker.release()
2598 self.waitUntilSettled()
Clark Boylan7603a372014-01-21 11:43:20 -08002599
2600 def test_queue_rate_limiting(self):
2601 "Test that DependentPipelines are rate limited with dep across window"
2602 self.config.set('zuul', 'layout_config',
2603 'tests/fixtures/layout-rate-limit.yaml')
2604 self.sched.reconfigure(self.config)
2605 self.worker.hold_jobs_in_build = True
2606 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2607 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2608 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
2609
2610 C.setDependsOn(B, 1)
2611 self.worker.addFailTest('project-test1', A)
2612
2613 A.addApproval('CRVW', 2)
2614 B.addApproval('CRVW', 2)
2615 C.addApproval('CRVW', 2)
2616
2617 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2618 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2619 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
2620 self.waitUntilSettled()
2621
2622 # Only A and B will have their merge jobs queued because
2623 # window is 2.
2624 self.assertEqual(len(self.builds), 2)
2625 self.assertEqual(self.builds[0].name, 'project-merge')
2626 self.assertEqual(self.builds[1].name, 'project-merge')
2627
2628 self.worker.release('.*-merge')
2629 self.waitUntilSettled()
2630 self.worker.release('.*-merge')
2631 self.waitUntilSettled()
2632
2633 # Only A and B will have their test jobs queued because
2634 # window is 2.
2635 self.assertEqual(len(self.builds), 4)
2636 self.assertEqual(self.builds[0].name, 'project-test1')
2637 self.assertEqual(self.builds[1].name, 'project-test2')
2638 self.assertEqual(self.builds[2].name, 'project-test1')
2639 self.assertEqual(self.builds[3].name, 'project-test2')
2640
2641 self.worker.release('project-.*')
2642 self.waitUntilSettled()
2643
2644 queue = self.sched.layout.pipelines['gate'].queues[0]
2645 # A failed so window is reduced by 1 to 1.
2646 self.assertEqual(queue.window, 1)
2647 self.assertEqual(queue.window_floor, 1)
2648 self.assertEqual(A.data['status'], 'NEW')
2649
2650 # Gate is reset and only B's merge job is queued because
2651 # window shrunk to 1.
2652 self.assertEqual(len(self.builds), 1)
2653 self.assertEqual(self.builds[0].name, 'project-merge')
2654
2655 self.worker.release('.*-merge')
2656 self.waitUntilSettled()
2657
2658 # Only B's test jobs are queued because window is still 1.
2659 self.assertEqual(len(self.builds), 2)
2660 self.assertEqual(self.builds[0].name, 'project-test1')
2661 self.assertEqual(self.builds[1].name, 'project-test2')
2662
2663 self.worker.release('project-.*')
2664 self.waitUntilSettled()
2665
2666 # B was successfully merged so window is increased to 2.
2667 self.assertEqual(queue.window, 2)
2668 self.assertEqual(queue.window_floor, 1)
2669 self.assertEqual(B.data['status'], 'MERGED')
2670
2671 # Only C is left and its merge job is queued.
2672 self.assertEqual(len(self.builds), 1)
2673 self.assertEqual(self.builds[0].name, 'project-merge')
2674
2675 self.worker.release('.*-merge')
2676 self.waitUntilSettled()
2677
2678 # After successful merge job the test jobs for C are queued.
2679 self.assertEqual(len(self.builds), 2)
2680 self.assertEqual(self.builds[0].name, 'project-test1')
2681 self.assertEqual(self.builds[1].name, 'project-test2')
2682
2683 self.worker.release('project-.*')
2684 self.waitUntilSettled()
2685
2686 # C successfully merged so window is bumped to 3.
2687 self.assertEqual(queue.window, 3)
2688 self.assertEqual(queue.window_floor, 1)
2689 self.assertEqual(C.data['status'], 'MERGED')
2690
2691 def test_queue_rate_limiting_dependent(self):
2692 "Test that DependentPipelines are rate limited with dep in window"
2693 self.config.set('zuul', 'layout_config',
2694 'tests/fixtures/layout-rate-limit.yaml')
2695 self.sched.reconfigure(self.config)
2696 self.worker.hold_jobs_in_build = True
2697 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2698 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2699 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
2700
2701 B.setDependsOn(A, 1)
2702
2703 self.worker.addFailTest('project-test1', A)
2704
2705 A.addApproval('CRVW', 2)
2706 B.addApproval('CRVW', 2)
2707 C.addApproval('CRVW', 2)
2708
2709 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2710 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2711 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
2712 self.waitUntilSettled()
2713
2714 # Only A and B will have their merge jobs queued because
2715 # window is 2.
2716 self.assertEqual(len(self.builds), 2)
2717 self.assertEqual(self.builds[0].name, 'project-merge')
2718 self.assertEqual(self.builds[1].name, 'project-merge')
2719
2720 self.worker.release('.*-merge')
2721 self.waitUntilSettled()
2722 self.worker.release('.*-merge')
2723 self.waitUntilSettled()
2724
2725 # Only A and B will have their test jobs queued because
2726 # window is 2.
2727 self.assertEqual(len(self.builds), 4)
2728 self.assertEqual(self.builds[0].name, 'project-test1')
2729 self.assertEqual(self.builds[1].name, 'project-test2')
2730 self.assertEqual(self.builds[2].name, 'project-test1')
2731 self.assertEqual(self.builds[3].name, 'project-test2')
2732
2733 self.worker.release('project-.*')
2734 self.waitUntilSettled()
2735
2736 queue = self.sched.layout.pipelines['gate'].queues[0]
2737 # A failed so window is reduced by 1 to 1.
2738 self.assertEqual(queue.window, 1)
2739 self.assertEqual(queue.window_floor, 1)
2740 self.assertEqual(A.data['status'], 'NEW')
2741 self.assertEqual(B.data['status'], 'NEW')
2742
2743 # Gate is reset and only C's merge job is queued because
2744 # window shrunk to 1 and A and B were dequeued.
2745 self.assertEqual(len(self.builds), 1)
2746 self.assertEqual(self.builds[0].name, 'project-merge')
2747
2748 self.worker.release('.*-merge')
2749 self.waitUntilSettled()
2750
2751 # Only C's test jobs are queued because window is still 1.
2752 self.assertEqual(len(self.builds), 2)
2753 self.assertEqual(self.builds[0].name, 'project-test1')
2754 self.assertEqual(self.builds[1].name, 'project-test2')
2755
2756 self.worker.release('project-.*')
2757 self.waitUntilSettled()
2758
2759 # C was successfully merged so window is increased to 2.
2760 self.assertEqual(queue.window, 2)
2761 self.assertEqual(queue.window_floor, 1)
2762 self.assertEqual(C.data['status'], 'MERGED')
Joshua Heskethba8776a2014-01-12 14:35:40 +08002763
2764 def test_worker_update_metadata(self):
2765 "Test if a worker can send back metadata about itself"
2766 self.worker.hold_jobs_in_build = True
2767
2768 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2769 A.addApproval('CRVW', 2)
2770 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2771 self.waitUntilSettled()
2772
2773 self.assertEqual(len(self.launcher.builds), 1)
2774
2775 self.log.debug('Current builds:')
2776 self.log.debug(self.launcher.builds)
2777
2778 start = time.time()
2779 while True:
2780 if time.time() - start > 10:
2781 raise Exception("Timeout waiting for gearman server to report "
2782 + "back to the client")
2783 build = self.launcher.builds.values()[0]
2784 if build.worker.name == "My Worker":
2785 break
2786 else:
2787 time.sleep(0)
2788
2789 self.log.debug(build)
2790 self.assertEqual("My Worker", build.worker.name)
2791 self.assertEqual("localhost", build.worker.hostname)
2792 self.assertEqual(['127.0.0.1', '192.168.1.1'], build.worker.ips)
2793 self.assertEqual("zuul.example.org", build.worker.fqdn)
2794 self.assertEqual("FakeBuilder", build.worker.program)
2795 self.assertEqual("v1.1", build.worker.version)
2796 self.assertEqual({'something': 'else'}, build.worker.extra)
2797
2798 self.worker.hold_jobs_in_build = False
2799 self.worker.release()
2800 self.waitUntilSettled()
Joshua Hesketh3979e3e2014-03-04 11:21:10 +11002801
2802 def test_footer_message(self):
2803 "Test a pipeline's footer message is correctly added to the report."
2804 self.config.set('zuul', 'layout_config',
2805 'tests/fixtures/layout-footer-message.yaml')
2806 self.sched.reconfigure(self.config)
2807 self.registerJobs()
2808
2809 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2810 A.addApproval('CRVW', 2)
2811 self.worker.addFailTest('test1', A)
2812 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2813 self.waitUntilSettled()
2814
2815 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2816 B.addApproval('CRVW', 2)
2817 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2818 self.waitUntilSettled()
2819
2820 self.assertEqual(2, len(self.smtp_messages))
2821
2822 failure_body = """\
2823Build failed. For information on how to proceed, see \
2824http://wiki.example.org/Test_Failures
2825
2826- test1 http://logs.example.com/1/1/gate/test1/0 : FAILURE in 0s
2827- test2 http://logs.example.com/1/1/gate/test2/1 : SUCCESS in 0s
2828
2829For CI problems and help debugging, contact ci@example.org"""
2830
2831 success_body = """\
2832Build succeeded.
2833
2834- test1 http://logs.example.com/2/1/gate/test1/2 : SUCCESS in 0s
2835- test2 http://logs.example.com/2/1/gate/test2/3 : SUCCESS in 0s
2836
2837For CI problems and help debugging, contact ci@example.org"""
2838
2839 self.assertEqual(failure_body, self.smtp_messages[0]['body'])
2840 self.assertEqual(success_body, self.smtp_messages[1]['body'])
Joshua Heskethb7179772014-01-30 23:30:46 +11002841
2842 def test_merge_failure_reporters(self):
2843 """Check that the config is set up correctly"""
2844
2845 self.config.set('zuul', 'layout_config',
2846 'tests/fixtures/layout-merge-failure.yaml')
2847 self.sched.reconfigure(self.config)
2848 self.registerJobs()
2849
2850 self.assertEqual(
2851 "Merge Failed.\n\nThis change was unable to be automatically "
2852 "merged with the current state of the repository. Please rebase "
2853 "your change and upload a new patchset.",
2854 self.sched.layout.pipelines['check'].merge_failure_message)
2855 self.assertEqual(
2856 "The merge failed! For more information...",
2857 self.sched.layout.pipelines['gate'].merge_failure_message)
2858
2859 self.assertEqual(
2860 len(self.sched.layout.pipelines['check'].merge_failure_actions), 1)
2861 self.assertEqual(
2862 len(self.sched.layout.pipelines['gate'].merge_failure_actions), 2)
2863
2864 self.assertTrue(isinstance(
2865 self.sched.layout.pipelines['check'].merge_failure_actions[0].
2866 reporter, zuul.reporter.gerrit.Reporter))
2867
2868 self.assertTrue(
2869 (
2870 isinstance(self.sched.layout.pipelines['gate'].
2871 merge_failure_actions[0].reporter,
2872 zuul.reporter.smtp.Reporter) and
2873 isinstance(self.sched.layout.pipelines['gate'].
2874 merge_failure_actions[1].reporter,
2875 zuul.reporter.gerrit.Reporter)
2876 ) or (
2877 isinstance(self.sched.layout.pipelines['gate'].
2878 merge_failure_actions[0].reporter,
2879 zuul.reporter.gerrit.Reporter) and
2880 isinstance(self.sched.layout.pipelines['gate'].
2881 merge_failure_actions[1].reporter,
2882 zuul.reporter.smtp.Reporter)
2883 )
2884 )
2885
2886 def test_merge_failure_reports(self):
2887 """Check that when a change fails to merge the correct message is sent
2888 to the correct reporter"""
2889 self.config.set('zuul', 'layout_config',
2890 'tests/fixtures/layout-merge-failure.yaml')
2891 self.sched.reconfigure(self.config)
2892 self.registerJobs()
2893
2894 # Check a test failure isn't reported to SMTP
2895 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2896 A.addApproval('CRVW', 2)
2897 self.worker.addFailTest('project-test1', A)
2898 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2899 self.waitUntilSettled()
2900
2901 self.assertEqual(3, len(self.history)) # 3 jobs
2902 self.assertEqual(0, len(self.smtp_messages))
2903
2904 # Check a merge failure is reported to SMTP
2905 # B should be merged, but C will conflict with B
2906 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2907 B.addPatchset(['conflict'])
2908 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
2909 C.addPatchset(['conflict'])
2910 B.addApproval('CRVW', 2)
2911 C.addApproval('CRVW', 2)
2912 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2913 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
2914 self.waitUntilSettled()
2915
2916 self.assertEqual(6, len(self.history)) # A and B jobs
2917 self.assertEqual(1, len(self.smtp_messages))
2918 self.assertEqual('The merge failed! For more information...',
2919 self.smtp_messages[0]['body'])
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11002920
2921 def test_swift_instructions(self):
2922 "Test that the correct swift instructions are sent to the workers"
2923 self.config.set('zuul', 'layout_config',
2924 'tests/fixtures/layout-swift.yaml')
2925 self.sched.reconfigure(self.config)
2926 self.registerJobs()
2927
2928 self.worker.hold_jobs_in_build = True
2929 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2930
2931 A.addApproval('CRVW', 2)
2932 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2933 self.waitUntilSettled()
2934
2935 self.assertEqual(
2936 "https://storage.example.org/V1/AUTH_account/merge_logs/1/1/1/"
2937 "gate/test-merge/",
Joshua Hesketh76dee532014-07-03 15:39:13 +10002938 self.builds[0].parameters['SWIFT_logs_URL'][:-7])
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11002939 self.assertEqual(5,
2940 len(self.builds[0].parameters['SWIFT_logs_HMAC_BODY'].
2941 split('\n')))
2942 self.assertIn('SWIFT_logs_SIGNATURE', self.builds[0].parameters)
2943
2944 self.assertEqual(
2945 "https://storage.example.org/V1/AUTH_account/logs/1/1/1/"
2946 "gate/test-test/",
Joshua Hesketh76dee532014-07-03 15:39:13 +10002947 self.builds[1].parameters['SWIFT_logs_URL'][:-7])
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11002948 self.assertEqual(5,
2949 len(self.builds[1].parameters['SWIFT_logs_HMAC_BODY'].
2950 split('\n')))
2951 self.assertIn('SWIFT_logs_SIGNATURE', self.builds[1].parameters)
2952
2953 self.assertEqual(
2954 "https://storage.example.org/V1/AUTH_account/stash/1/1/1/"
2955 "gate/test-test/",
Joshua Hesketh76dee532014-07-03 15:39:13 +10002956 self.builds[1].parameters['SWIFT_MOSTLY_URL'][:-7])
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11002957 self.assertEqual(5,
2958 len(self.builds[1].
2959 parameters['SWIFT_MOSTLY_HMAC_BODY'].split('\n')))
2960 self.assertIn('SWIFT_MOSTLY_SIGNATURE', self.builds[1].parameters)
2961
2962 self.worker.hold_jobs_in_build = False
2963 self.worker.release()
2964 self.waitUntilSettled()
Joshua Hesketh85af4e92014-02-21 08:28:58 -08002965
2966 def test_client_get_running_jobs(self):
2967 "Test that the RPC client can get a list of running jobs"
2968 self.worker.hold_jobs_in_build = True
2969 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2970 A.addApproval('CRVW', 2)
2971 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2972 self.waitUntilSettled()
2973
2974 client = zuul.rpcclient.RPCClient('127.0.0.1',
2975 self.gearman_server.port)
2976
2977 # Wait for gearman server to send the initial workData back to zuul
2978 start = time.time()
2979 while True:
2980 if time.time() - start > 10:
2981 raise Exception("Timeout waiting for gearman server to report "
2982 + "back to the client")
2983 build = self.launcher.builds.values()[0]
2984 if build.worker.name == "My Worker":
2985 break
2986 else:
2987 time.sleep(0)
2988
2989 running_items = client.get_running_jobs()
2990
2991 self.assertEqual(1, len(running_items))
2992 running_item = running_items[0]
2993 self.assertEqual([], running_item['failing_reasons'])
2994 self.assertEqual([], running_item['items_behind'])
2995 self.assertEqual('https://hostname/1', running_item['url'])
2996 self.assertEqual(None, running_item['item_ahead'])
2997 self.assertEqual('org/project', running_item['project'])
2998 self.assertEqual(None, running_item['remaining_time'])
2999 self.assertEqual(True, running_item['active'])
3000 self.assertEqual('1,1', running_item['id'])
3001
3002 self.assertEqual(3, len(running_item['jobs']))
3003 for job in running_item['jobs']:
3004 if job['name'] == 'project-merge':
3005 self.assertEqual('project-merge', job['name'])
3006 self.assertEqual('gate', job['pipeline'])
3007 self.assertEqual(False, job['retry'])
3008 self.assertEqual(13, len(job['parameters']))
3009 self.assertEqual('https://server/job/project-merge/0/',
3010 job['url'])
3011 self.assertEqual(7, len(job['worker']))
3012 self.assertEqual(False, job['canceled'])
3013 self.assertEqual(True, job['voting'])
3014 self.assertEqual(None, job['result'])
3015 self.assertEqual('gate', job['pipeline'])
3016 break
3017
3018 self.worker.hold_jobs_in_build = False
3019 self.worker.release()
3020 self.waitUntilSettled()
3021
3022 running_items = client.get_running_jobs()
3023 self.assertEqual(0, len(running_items))
James E. Blairbadc1ad2014-04-28 13:55:14 -07003024
3025 def test_nonvoting_pipeline(self):
3026 "Test that a nonvoting pipeline (experimental) can still report"
3027
Joshua Heskethcc017ea2014-04-30 19:55:25 +10003028 A = self.fake_gerrit.addFakeChange('org/experimental-project',
3029 'master', 'A')
James E. Blairbadc1ad2014-04-28 13:55:14 -07003030 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3031 self.waitUntilSettled()
Joshua Heskethcc017ea2014-04-30 19:55:25 +10003032 self.assertEqual(
3033 self.getJobFromHistory('experimental-project-test').result,
3034 'SUCCESS')
James E. Blairbadc1ad2014-04-28 13:55:14 -07003035 self.assertEqual(A.reported, 1)
James E. Blair5ee24252014-12-30 10:12:29 -08003036
3037 def test_crd_gate(self):
3038 "Test cross-repo dependencies"
3039 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3040 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3041 A.addApproval('CRVW', 2)
3042 B.addApproval('CRVW', 2)
3043
3044 AM2 = self.fake_gerrit.addFakeChange('org/project1', 'master', 'AM2')
3045 AM1 = self.fake_gerrit.addFakeChange('org/project1', 'master', 'AM1')
3046 AM2.setMerged()
3047 AM1.setMerged()
3048
3049 BM2 = self.fake_gerrit.addFakeChange('org/project2', 'master', 'BM2')
3050 BM1 = self.fake_gerrit.addFakeChange('org/project2', 'master', 'BM1')
3051 BM2.setMerged()
3052 BM1.setMerged()
3053
3054 # A -> AM1 -> AM2
3055 # B -> BM1 -> BM2
3056 # A Depends-On: B
3057 # M2 is here to make sure it is never queried. If it is, it
3058 # means zuul is walking down the entire history of merged
3059 # changes.
3060
3061 B.setDependsOn(BM1, 1)
3062 BM1.setDependsOn(BM2, 1)
3063
3064 A.setDependsOn(AM1, 1)
3065 AM1.setDependsOn(AM2, 1)
3066
3067 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3068 A.subject, B.data['id'])
3069
3070 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3071 self.waitUntilSettled()
3072
3073 self.assertEqual(A.data['status'], 'NEW')
3074 self.assertEqual(B.data['status'], 'NEW')
3075
3076 source = self.sched.layout.pipelines['gate'].source
3077 source.maintainCache([])
3078
3079 self.worker.hold_jobs_in_build = True
3080 B.addApproval('APRV', 1)
3081 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3082 self.waitUntilSettled()
3083
3084 self.worker.release('.*-merge')
3085 self.waitUntilSettled()
3086 self.worker.release('.*-merge')
3087 self.waitUntilSettled()
3088 self.worker.hold_jobs_in_build = False
3089 self.worker.release()
3090 self.waitUntilSettled()
3091
3092 self.assertEqual(AM2.queried, 0)
3093 self.assertEqual(BM2.queried, 0)
3094 self.assertEqual(A.data['status'], 'MERGED')
3095 self.assertEqual(B.data['status'], 'MERGED')
3096 self.assertEqual(A.reported, 2)
3097 self.assertEqual(B.reported, 2)
3098
James E. Blair8f78d882015-02-05 08:51:37 -08003099 self.assertEqual(self.getJobFromHistory('project1-merge').changes,
3100 '2,1 1,1')
3101
3102 def test_crd_branch(self):
3103 "Test cross-repo dependencies in multiple branches"
3104 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3105 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3106 C = self.fake_gerrit.addFakeChange('org/project2', 'mp', 'C')
3107 C.data['id'] = B.data['id']
3108 A.addApproval('CRVW', 2)
3109 B.addApproval('CRVW', 2)
3110 C.addApproval('CRVW', 2)
3111
3112 # A Depends-On: B+C
3113 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3114 A.subject, B.data['id'])
3115
3116 self.worker.hold_jobs_in_build = True
3117 B.addApproval('APRV', 1)
3118 C.addApproval('APRV', 1)
3119 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3120 self.waitUntilSettled()
3121
3122 self.worker.release('.*-merge')
3123 self.waitUntilSettled()
3124 self.worker.release('.*-merge')
3125 self.waitUntilSettled()
3126 self.worker.release('.*-merge')
3127 self.waitUntilSettled()
3128 self.worker.hold_jobs_in_build = False
3129 self.worker.release()
3130 self.waitUntilSettled()
3131
3132 self.assertEqual(A.data['status'], 'MERGED')
3133 self.assertEqual(B.data['status'], 'MERGED')
3134 self.assertEqual(C.data['status'], 'MERGED')
3135 self.assertEqual(A.reported, 2)
3136 self.assertEqual(B.reported, 2)
3137 self.assertEqual(C.reported, 2)
3138
3139 self.assertEqual(self.getJobFromHistory('project1-merge').changes,
3140 '2,1 3,1 1,1')
3141
3142 def test_crd_multiline(self):
3143 "Test multiple depends-on lines in commit"
3144 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3145 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3146 C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
3147 A.addApproval('CRVW', 2)
3148 B.addApproval('CRVW', 2)
3149 C.addApproval('CRVW', 2)
3150
3151 # A Depends-On: B+C
3152 A.data['commitMessage'] = '%s\n\nDepends-On: %s\nDepends-On: %s\n' % (
3153 A.subject, B.data['id'], C.data['id'])
3154
3155 self.worker.hold_jobs_in_build = True
3156 B.addApproval('APRV', 1)
3157 C.addApproval('APRV', 1)
3158 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3159 self.waitUntilSettled()
3160
3161 self.worker.release('.*-merge')
3162 self.waitUntilSettled()
3163 self.worker.release('.*-merge')
3164 self.waitUntilSettled()
3165 self.worker.release('.*-merge')
3166 self.waitUntilSettled()
3167 self.worker.hold_jobs_in_build = False
3168 self.worker.release()
3169 self.waitUntilSettled()
3170
3171 self.assertEqual(A.data['status'], 'MERGED')
3172 self.assertEqual(B.data['status'], 'MERGED')
3173 self.assertEqual(C.data['status'], 'MERGED')
3174 self.assertEqual(A.reported, 2)
3175 self.assertEqual(B.reported, 2)
3176 self.assertEqual(C.reported, 2)
3177
3178 self.assertEqual(self.getJobFromHistory('project1-merge').changes,
3179 '2,1 3,1 1,1')
James E. Blair5ee24252014-12-30 10:12:29 -08003180
3181 def test_crd_unshared_gate(self):
3182 "Test cross-repo dependencies in unshared gate queues"
3183 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3184 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
3185 A.addApproval('CRVW', 2)
3186 B.addApproval('CRVW', 2)
3187
3188 # A Depends-On: B
3189 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3190 A.subject, B.data['id'])
3191
3192 # A and B do not share a queue, make sure that A is unable to
3193 # enqueue B (and therefore, A is unable to be enqueued).
3194 B.addApproval('APRV', 1)
3195 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3196 self.waitUntilSettled()
3197
3198 self.assertEqual(A.data['status'], 'NEW')
3199 self.assertEqual(B.data['status'], 'NEW')
3200 self.assertEqual(A.reported, 0)
3201 self.assertEqual(B.reported, 0)
3202 self.assertEqual(len(self.history), 0)
3203
3204 # Enqueue and merge B alone.
3205 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
3206 self.waitUntilSettled()
3207
3208 self.assertEqual(B.data['status'], 'MERGED')
3209 self.assertEqual(B.reported, 2)
3210
3211 # Now that B is merged, A should be able to be enqueued and
3212 # merged.
3213 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3214 self.waitUntilSettled()
3215
3216 self.assertEqual(A.data['status'], 'MERGED')
3217 self.assertEqual(A.reported, 2)
3218
3219 def test_crd_cycle(self):
3220 "Test cross-repo dependency cycles"
3221 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3222 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3223 A.addApproval('CRVW', 2)
3224 B.addApproval('CRVW', 2)
3225
3226 # A -> B -> A (via commit-depends)
3227
3228 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3229 A.subject, B.data['id'])
3230 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3231 B.subject, A.data['id'])
3232
3233 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3234 self.waitUntilSettled()
3235
3236 self.assertEqual(A.reported, 0)
3237 self.assertEqual(B.reported, 0)
3238 self.assertEqual(A.data['status'], 'NEW')
3239 self.assertEqual(B.data['status'], 'NEW')
James E. Blairbfb8e042014-12-30 17:01:44 -08003240
3241 def test_crd_check(self):
3242 "Test cross-repo dependencies in independent pipelines"
3243
3244 self.gearman_server.hold_jobs_in_queue = True
3245 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3246 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3247
3248 # A Depends-On: B
3249 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3250 A.subject, B.data['id'])
3251
3252 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3253 self.waitUntilSettled()
3254
3255 queue = self.gearman_server.getQueue()
3256 ref = self.getParameter(queue[-1], 'ZUUL_REF')
3257 self.gearman_server.hold_jobs_in_queue = False
3258 self.gearman_server.release()
3259 self.waitUntilSettled()
3260
3261 path = os.path.join(self.git_root, "org/project1")
3262 repo = git.Repo(path)
3263 repo_messages = [c.message.strip() for c in repo.iter_commits(ref)]
3264 repo_messages.reverse()
3265 correct_messages = ['initial commit', 'A-1']
3266 self.assertEqual(repo_messages, correct_messages)
3267
3268 path = os.path.join(self.git_root, "org/project2")
3269 repo = git.Repo(path)
3270 repo_messages = [c.message.strip() for c in repo.iter_commits(ref)]
3271 repo_messages.reverse()
3272 correct_messages = ['initial commit', 'B-1']
3273 self.assertEqual(repo_messages, correct_messages)
3274
3275 self.assertEqual(A.data['status'], 'NEW')
3276 self.assertEqual(B.data['status'], 'NEW')
3277 self.assertEqual(A.reported, 1)
3278 self.assertEqual(B.reported, 0)
3279
3280 self.assertEqual(self.history[0].changes, '2,1 1,1')
3281 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 0)
James E. Blair8f78d882015-02-05 08:51:37 -08003282
James E. Blairdbfe1cd2015-02-07 11:41:19 -08003283 def test_crd_check_git_depends(self):
3284 "Test single-repo dependencies in independent pipelines"
3285 self.gearman_server.hold_jobs_in_queue = True
3286 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3287 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
3288
3289 # Add two git-dependent changes and make sure they both report
3290 # success.
3291 B.setDependsOn(A, 1)
3292 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3293 self.waitUntilSettled()
3294 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
3295 self.waitUntilSettled()
3296
3297 self.gearman_server.hold_jobs_in_queue = False
3298 self.gearman_server.release()
3299 self.waitUntilSettled()
3300
3301 self.assertEqual(A.data['status'], 'NEW')
3302 self.assertEqual(B.data['status'], 'NEW')
3303 self.assertEqual(A.reported, 1)
3304 self.assertEqual(B.reported, 1)
3305
3306 self.assertEqual(self.history[0].changes, '1,1')
3307 self.assertEqual(self.history[-1].changes, '1,1 2,1')
3308 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 0)
3309
3310 self.assertIn('Build succeeded', A.messages[0])
3311 self.assertIn('Build succeeded', B.messages[0])
3312
3313 def test_crd_check_duplicate(self):
3314 "Test duplicate check in independent pipelines"
3315 self.gearman_server.hold_jobs_in_queue = True
3316 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3317 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
3318 check_pipeline = self.sched.layout.pipelines['check']
3319
3320 # Add two git-dependent changes...
3321 B.setDependsOn(A, 1)
3322 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
3323 self.waitUntilSettled()
3324 self.assertEqual(len(check_pipeline.getAllItems()), 2)
3325
3326 # ...make sure the live one is not duplicated...
3327 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
3328 self.waitUntilSettled()
3329 self.assertEqual(len(check_pipeline.getAllItems()), 2)
3330
3331 # ...but the non-live one is able to be.
3332 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3333 self.waitUntilSettled()
3334 self.assertEqual(len(check_pipeline.getAllItems()), 3)
3335
3336 self.gearman_server.hold_jobs_in_queue = False
3337 self.gearman_server.release('.*-merge')
3338 self.waitUntilSettled()
3339 self.gearman_server.release('.*-merge')
3340 self.waitUntilSettled()
3341 self.gearman_server.release()
3342 self.waitUntilSettled()
3343
3344 self.assertEqual(A.data['status'], 'NEW')
3345 self.assertEqual(B.data['status'], 'NEW')
3346 self.assertEqual(A.reported, 1)
3347 self.assertEqual(B.reported, 1)
3348
3349 self.assertEqual(self.history[0].changes, '1,1 2,1')
3350 self.assertEqual(self.history[1].changes, '1,1')
3351 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 0)
3352
3353 self.assertIn('Build succeeded', A.messages[0])
3354 self.assertIn('Build succeeded', B.messages[0])
3355
James E. Blair8f78d882015-02-05 08:51:37 -08003356 def test_crd_check_reconfiguration(self):
3357 "Test cross-repo dependencies re-enqueued in independent pipelines"
3358
3359 self.gearman_server.hold_jobs_in_queue = True
3360 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3361 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3362
3363 # A Depends-On: B
3364 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3365 A.subject, B.data['id'])
3366
3367 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3368 self.waitUntilSettled()
3369
3370 self.sched.reconfigure(self.config)
3371
3372 # Make sure the items still share a change queue, and the
3373 # first one is not live.
3374 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 1)
3375 queue = self.sched.layout.pipelines['check'].queues[0]
3376 first_item = queue.queue[0]
3377 for item in queue.queue:
3378 self.assertEqual(item.queue, first_item.queue)
3379 self.assertFalse(first_item.live)
3380 self.assertTrue(queue.queue[1].live)
3381
3382 self.gearman_server.hold_jobs_in_queue = False
3383 self.gearman_server.release()
3384 self.waitUntilSettled()
3385
3386 self.assertEqual(A.data['status'], 'NEW')
3387 self.assertEqual(B.data['status'], 'NEW')
3388 self.assertEqual(A.reported, 1)
3389 self.assertEqual(B.reported, 0)
3390
3391 self.assertEqual(self.history[0].changes, '2,1 1,1')
3392 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 0)
James E. Blair17dd6772015-02-09 14:45:18 -08003393
3394 def test_crd_check_ignore_dependencies(self):
3395 "Test cross-repo dependencies can be ignored"
3396 self.config.set('zuul', 'layout_config',
3397 'tests/fixtures/layout-ignore-dependencies.yaml')
3398 self.sched.reconfigure(self.config)
3399 self.registerJobs()
3400
3401 self.gearman_server.hold_jobs_in_queue = True
3402 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3403 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3404 C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
3405
3406 # A Depends-On: B
3407 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3408 A.subject, B.data['id'])
3409 # C git-depends on B
3410 C.setDependsOn(B, 1)
3411 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3412 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
3413 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
3414 self.waitUntilSettled()
3415
3416 # Make sure none of the items share a change queue, and all
3417 # are live.
3418 check_pipeline = self.sched.layout.pipelines['check']
3419 self.assertEqual(len(check_pipeline.queues), 3)
3420 self.assertEqual(len(check_pipeline.getAllItems()), 3)
3421 for item in check_pipeline.getAllItems():
3422 self.assertTrue(item.live)
3423
3424 self.gearman_server.hold_jobs_in_queue = False
3425 self.gearman_server.release()
3426 self.waitUntilSettled()
3427
3428 self.assertEqual(A.data['status'], 'NEW')
3429 self.assertEqual(B.data['status'], 'NEW')
3430 self.assertEqual(C.data['status'], 'NEW')
3431 self.assertEqual(A.reported, 1)
3432 self.assertEqual(B.reported, 1)
3433 self.assertEqual(C.reported, 1)
3434
3435 # Each job should have tested exactly one change
3436 for job in self.history:
3437 self.assertEqual(len(job.changes.split()), 1)