blob: 059f155f42e679fb22f2eb15b9739bb4e7d6b90f [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
Antoine Mussobd86a312014-01-08 14:51:33 +01001500 def test_abandoned_change_dequeues(self):
1501 "Test that an abandoned change is dequeued"
1502
1503 self.worker.hold_jobs_in_build = True
1504
1505 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1506 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1507 self.waitUntilSettled()
1508 self.assertEqual(len(self.builds), 1, "One job being built (on hold)")
1509 self.assertEqual(self.builds[0].name, 'project-merge')
1510
1511 self.fake_gerrit.addEvent(A.getChangeAbandonedEvent())
1512 self.waitUntilSettled()
1513
1514 # For debugging purposes...
Joshua Hesketh29d99b72014-08-19 16:27:42 +10001515 # for pipeline in self.sched.layout.pipelines.values():
1516 # for queue in pipeline.queues:
1517 # self.log.info("pipepline %s queue %s contents %s" % (
1518 # pipeline.name, queue.name, queue.queue))
Antoine Mussobd86a312014-01-08 14:51:33 +01001519
1520 self.worker.release('.*-merge')
1521 self.waitUntilSettled()
1522
1523 self.assertEqual(len(self.builds), 0, "No job running")
1524 self.assertEmptyQueues()
1525 self.assertEqual(len(self.history), 1, "Only one build in history")
1526 self.assertEqual(self.history[0].result, 'ABORTED',
1527 'Build should have been aborted')
1528 self.assertEqual(A.reported, 0, "Abandoned change should not report")
1529
Arx Cruzb1b010d2013-10-28 19:49:59 -02001530 def test_zuul_url_return(self):
1531 "Test if ZUUL_URL is returning when zuul_url is set in zuul.conf"
James E. Blair4076e2b2014-01-28 12:42:20 -08001532 self.assertTrue(self.sched.config.has_option('merger', 'zuul_url'))
Arx Cruzb1b010d2013-10-28 19:49:59 -02001533 self.worker.hold_jobs_in_build = True
1534
1535 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1536 A.addApproval('CRVW', 2)
1537 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1538 self.waitUntilSettled()
1539
1540 self.assertEqual(len(self.builds), 1)
1541 for build in self.builds:
1542 self.assertTrue('ZUUL_URL' in build.parameters)
1543
1544 self.worker.hold_jobs_in_build = False
1545 self.worker.release()
1546 self.waitUntilSettled()
1547
James E. Blair2fa50962013-01-30 21:50:41 -08001548 def test_new_patchset_dequeues_old_on_head(self):
1549 "Test that a new patchset causes the old to be dequeued (at head)"
1550 # D -> C (depends on B) -> B (depends on A) -> A -> M
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001551 self.worker.hold_jobs_in_build = True
James E. Blair2fa50962013-01-30 21:50:41 -08001552 M = self.fake_gerrit.addFakeChange('org/project', 'master', 'M')
1553 M.setMerged()
1554 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1555 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1556 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1557 D = self.fake_gerrit.addFakeChange('org/project', 'master', 'D')
1558 A.addApproval('CRVW', 2)
1559 B.addApproval('CRVW', 2)
1560 C.addApproval('CRVW', 2)
1561 D.addApproval('CRVW', 2)
1562
1563 C.setDependsOn(B, 1)
1564 B.setDependsOn(A, 1)
1565 A.setDependsOn(M, 1)
1566
1567 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1568 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1569 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1570 self.fake_gerrit.addEvent(D.addApproval('APRV', 1))
1571 self.waitUntilSettled()
1572
1573 A.addPatchset()
1574 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
1575 self.waitUntilSettled()
1576
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001577 self.worker.hold_jobs_in_build = False
1578 self.worker.release()
James E. Blair2fa50962013-01-30 21:50:41 -08001579 self.waitUntilSettled()
1580
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001581 self.assertEqual(A.data['status'], 'NEW')
1582 self.assertEqual(A.reported, 2)
1583 self.assertEqual(B.data['status'], 'NEW')
1584 self.assertEqual(B.reported, 2)
1585 self.assertEqual(C.data['status'], 'NEW')
1586 self.assertEqual(C.reported, 2)
1587 self.assertEqual(D.data['status'], 'MERGED')
1588 self.assertEqual(D.reported, 2)
1589 self.assertEqual(len(self.history), 7)
James E. Blair2fa50962013-01-30 21:50:41 -08001590
1591 def test_new_patchset_dequeues_old_without_dependents(self):
1592 "Test that a new patchset causes only the old to be dequeued"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001593 self.worker.hold_jobs_in_build = True
James E. Blair2fa50962013-01-30 21:50:41 -08001594 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1595 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1596 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1597 A.addApproval('CRVW', 2)
1598 B.addApproval('CRVW', 2)
1599 C.addApproval('CRVW', 2)
1600
1601 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1602 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1603 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1604 self.waitUntilSettled()
1605
1606 B.addPatchset()
1607 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(2))
1608 self.waitUntilSettled()
1609
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001610 self.worker.hold_jobs_in_build = False
1611 self.worker.release()
James E. Blair2fa50962013-01-30 21:50:41 -08001612 self.waitUntilSettled()
1613
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001614 self.assertEqual(A.data['status'], 'MERGED')
1615 self.assertEqual(A.reported, 2)
1616 self.assertEqual(B.data['status'], 'NEW')
1617 self.assertEqual(B.reported, 2)
1618 self.assertEqual(C.data['status'], 'MERGED')
1619 self.assertEqual(C.reported, 2)
1620 self.assertEqual(len(self.history), 9)
James E. Blair2fa50962013-01-30 21:50:41 -08001621
1622 def test_new_patchset_dequeues_old_independent_queue(self):
1623 "Test that a new patchset causes the old to be dequeued (independent)"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001624 self.worker.hold_jobs_in_build = True
James E. Blair2fa50962013-01-30 21:50:41 -08001625 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1626 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1627 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
1628 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1629 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1630 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
1631 self.waitUntilSettled()
1632
1633 B.addPatchset()
1634 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(2))
1635 self.waitUntilSettled()
1636
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001637 self.worker.hold_jobs_in_build = False
1638 self.worker.release()
James E. Blair2fa50962013-01-30 21:50:41 -08001639 self.waitUntilSettled()
1640
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001641 self.assertEqual(A.data['status'], 'NEW')
1642 self.assertEqual(A.reported, 1)
1643 self.assertEqual(B.data['status'], 'NEW')
1644 self.assertEqual(B.reported, 1)
1645 self.assertEqual(C.data['status'], 'NEW')
1646 self.assertEqual(C.reported, 1)
1647 self.assertEqual(len(self.history), 10)
1648 self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 1)
James E. Blair7d0dedc2013-02-21 17:26:09 -08001649
James E. Blair18c64442014-03-18 10:14:45 -07001650 def test_noop_job(self):
1651 "Test that the internal noop job works"
1652 A = self.fake_gerrit.addFakeChange('org/noop-project', 'master', 'A')
1653 A.addApproval('CRVW', 2)
1654 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1655 self.waitUntilSettled()
1656
1657 self.assertEqual(len(self.gearman_server.getQueue()), 0)
1658 self.assertTrue(self.sched._areAllBuildsComplete())
1659 self.assertEqual(len(self.history), 0)
1660 self.assertEqual(A.data['status'], 'MERGED')
1661 self.assertEqual(A.reported, 2)
1662
James E. Blair7d0dedc2013-02-21 17:26:09 -08001663 def test_zuul_refs(self):
1664 "Test that zuul refs exist and have the right changes"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001665 self.worker.hold_jobs_in_build = True
James E. Blair7d0dedc2013-02-21 17:26:09 -08001666 M1 = self.fake_gerrit.addFakeChange('org/project1', 'master', 'M1')
1667 M1.setMerged()
1668 M2 = self.fake_gerrit.addFakeChange('org/project2', 'master', 'M2')
1669 M2.setMerged()
1670
1671 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
1672 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
1673 C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
1674 D = self.fake_gerrit.addFakeChange('org/project2', 'master', 'D')
1675 A.addApproval('CRVW', 2)
1676 B.addApproval('CRVW', 2)
1677 C.addApproval('CRVW', 2)
1678 D.addApproval('CRVW', 2)
1679 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1680 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1681 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
1682 self.fake_gerrit.addEvent(D.addApproval('APRV', 1))
1683
1684 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001685 self.worker.release('.*-merge')
James E. Blair7d0dedc2013-02-21 17:26:09 -08001686 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001687 self.worker.release('.*-merge')
James E. Blair7d0dedc2013-02-21 17:26:09 -08001688 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001689 self.worker.release('.*-merge')
James E. Blair7d0dedc2013-02-21 17:26:09 -08001690 self.waitUntilSettled()
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001691 self.worker.release('.*-merge')
James E. Blair7d0dedc2013-02-21 17:26:09 -08001692 self.waitUntilSettled()
1693
James E. Blair7d0dedc2013-02-21 17:26:09 -08001694 a_zref = b_zref = c_zref = d_zref = None
Monty Taylor6bef8ef2013-06-02 08:17:12 -04001695 for x in self.builds:
James E. Blair7d0dedc2013-02-21 17:26:09 -08001696 if x.parameters['ZUUL_CHANGE'] == '3':
1697 a_zref = x.parameters['ZUUL_REF']
1698 if x.parameters['ZUUL_CHANGE'] == '4':
1699 b_zref = x.parameters['ZUUL_REF']
1700 if x.parameters['ZUUL_CHANGE'] == '5':
1701 c_zref = x.parameters['ZUUL_REF']
1702 if x.parameters['ZUUL_CHANGE'] == '6':
1703 d_zref = x.parameters['ZUUL_REF']
1704
1705 # There are... four... refs.
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001706 self.assertIsNotNone(a_zref)
1707 self.assertIsNotNone(b_zref)
1708 self.assertIsNotNone(c_zref)
1709 self.assertIsNotNone(d_zref)
James E. Blair7d0dedc2013-02-21 17:26:09 -08001710
1711 # And they should all be different
1712 refs = set([a_zref, b_zref, c_zref, d_zref])
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001713 self.assertEqual(len(refs), 4)
James E. Blair7d0dedc2013-02-21 17:26:09 -08001714
1715 # a ref should have a, not b, and should not be in project2
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001716 self.assertTrue(self.ref_has_change(a_zref, A))
1717 self.assertFalse(self.ref_has_change(a_zref, B))
1718 self.assertFalse(self.ref_has_change(a_zref, M2))
James E. Blair7d0dedc2013-02-21 17:26:09 -08001719
1720 # b ref should have a and b, and should not be in project2
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001721 self.assertTrue(self.ref_has_change(b_zref, A))
1722 self.assertTrue(self.ref_has_change(b_zref, B))
1723 self.assertFalse(self.ref_has_change(b_zref, M2))
James E. Blair7d0dedc2013-02-21 17:26:09 -08001724
1725 # c ref should have a and b in 1, c in 2
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001726 self.assertTrue(self.ref_has_change(c_zref, A))
1727 self.assertTrue(self.ref_has_change(c_zref, B))
1728 self.assertTrue(self.ref_has_change(c_zref, C))
1729 self.assertFalse(self.ref_has_change(c_zref, D))
James E. Blair7d0dedc2013-02-21 17:26:09 -08001730
1731 # d ref should have a and b in 1, c and d in 2
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001732 self.assertTrue(self.ref_has_change(d_zref, A))
1733 self.assertTrue(self.ref_has_change(d_zref, B))
1734 self.assertTrue(self.ref_has_change(d_zref, C))
1735 self.assertTrue(self.ref_has_change(d_zref, D))
James E. Blair7d0dedc2013-02-21 17:26:09 -08001736
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001737 self.worker.hold_jobs_in_build = False
1738 self.worker.release()
James E. Blair7d0dedc2013-02-21 17:26:09 -08001739 self.waitUntilSettled()
1740
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001741 self.assertEqual(A.data['status'], 'MERGED')
1742 self.assertEqual(A.reported, 2)
1743 self.assertEqual(B.data['status'], 'MERGED')
1744 self.assertEqual(B.reported, 2)
1745 self.assertEqual(C.data['status'], 'MERGED')
1746 self.assertEqual(C.reported, 2)
1747 self.assertEqual(D.data['status'], 'MERGED')
1748 self.assertEqual(D.reported, 2)
James E. Blair70c71582013-03-06 08:50:50 -08001749
James E. Blair4a28a882013-08-23 15:17:33 -07001750 def test_rerun_on_error(self):
1751 "Test that if a worker fails to run a job, it is run again"
1752 self.worker.hold_jobs_in_build = True
1753 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1754 A.addApproval('CRVW', 2)
1755 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1756 self.waitUntilSettled()
1757
1758 self.builds[0].run_error = True
1759 self.worker.hold_jobs_in_build = False
1760 self.worker.release()
1761 self.waitUntilSettled()
1762 self.assertEqual(self.countJobResults(self.history, 'RUN_ERROR'), 1)
1763 self.assertEqual(self.countJobResults(self.history, 'SUCCESS'), 3)
1764
James E. Blair412e5582013-04-22 15:50:12 -07001765 def test_statsd(self):
1766 "Test each of the statsd methods used in the scheduler"
1767 import extras
1768 statsd = extras.try_import('statsd.statsd')
1769 statsd.incr('test-incr')
1770 statsd.timing('test-timing', 3)
Alex Gaynor813d39b2014-05-17 16:17:16 -07001771 statsd.gauge('test-gauge', 12)
James E. Blair412e5582013-04-22 15:50:12 -07001772 self.assertReportedStat('test-incr', '1|c')
1773 self.assertReportedStat('test-timing', '3|ms')
Alex Gaynor813d39b2014-05-17 16:17:16 -07001774 self.assertReportedStat('test-gauge', '12|g')
James E. Blair412e5582013-04-22 15:50:12 -07001775
James E. Blairdad52252014-02-07 16:59:17 -08001776 def test_stuck_job_cleanup(self):
1777 "Test that pending jobs are cleaned up if removed from layout"
James E. Blair18c64442014-03-18 10:14:45 -07001778 # This job won't be registered at startup because it is not in
1779 # the standard layout, but we need it to already be registerd
1780 # for when we reconfigure, as that is when Zuul will attempt
1781 # to run the new job.
1782 self.worker.registerFunction('build:gate-noop')
James E. Blairdad52252014-02-07 16:59:17 -08001783 self.gearman_server.hold_jobs_in_queue = True
1784 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1785 A.addApproval('CRVW', 2)
1786 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1787 self.waitUntilSettled()
1788 self.assertEqual(len(self.gearman_server.getQueue()), 1)
1789
1790 self.config.set('zuul', 'layout_config',
1791 'tests/fixtures/layout-no-jobs.yaml')
1792 self.sched.reconfigure(self.config)
1793 self.waitUntilSettled()
1794
James E. Blair18c64442014-03-18 10:14:45 -07001795 self.gearman_server.release('gate-noop')
James E. Blairdad52252014-02-07 16:59:17 -08001796 self.waitUntilSettled()
1797 self.assertEqual(len(self.gearman_server.getQueue()), 0)
1798 self.assertTrue(self.sched._areAllBuildsComplete())
1799
1800 self.assertEqual(len(self.history), 1)
James E. Blair18c64442014-03-18 10:14:45 -07001801 self.assertEqual(self.history[0].name, 'gate-noop')
James E. Blairdad52252014-02-07 16:59:17 -08001802 self.assertEqual(self.history[0].result, 'SUCCESS')
1803
James E. Blair70c71582013-03-06 08:50:50 -08001804 def test_file_jobs(self):
1805 "Test that file jobs run only when appropriate"
1806 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1807 A.addPatchset(['pip-requires'])
1808 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1809 A.addApproval('CRVW', 2)
1810 B.addApproval('CRVW', 2)
1811 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1812 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
1813 self.waitUntilSettled()
1814
Monty Taylor6bef8ef2013-06-02 08:17:12 -04001815 testfile_jobs = [x for x in self.history
James E. Blair70c71582013-03-06 08:50:50 -08001816 if x.name == 'project-testfile']
1817
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001818 self.assertEqual(len(testfile_jobs), 1)
1819 self.assertEqual(testfile_jobs[0].changes, '1,2')
1820 self.assertEqual(A.data['status'], 'MERGED')
1821 self.assertEqual(A.reported, 2)
1822 self.assertEqual(B.data['status'], 'MERGED')
1823 self.assertEqual(B.reported, 2)
James E. Blair3c5e5b52013-04-26 11:17:03 -07001824
1825 def test_test_config(self):
1826 "Test that we can test the config"
1827 sched = zuul.scheduler.Scheduler()
James E. Blair6c358e72013-07-29 17:06:47 -07001828 sched.registerTrigger(None, 'gerrit')
James E. Blair63bb0ef2013-07-29 17:14:51 -07001829 sched.registerTrigger(None, 'timer')
James E. Blairc494d542014-08-06 09:23:52 -07001830 sched.registerTrigger(None, 'zuul')
Clark Boylanb640e052014-04-03 16:41:46 -07001831 sched.testConfig(self.config.get('zuul', 'layout_config'))
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001832
1833 def test_build_description(self):
1834 "Test that build descriptions update"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001835 self.worker.registerFunction('set_description:' +
1836 self.worker.worker_id)
1837
1838 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1839 A.addApproval('CRVW', 2)
1840 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1841 self.waitUntilSettled()
Monty Taylor6bef8ef2013-06-02 08:17:12 -04001842 desc = self.history[0].description
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001843 self.log.debug("Description: %s" % desc)
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001844 self.assertTrue(re.search("Branch.*master", desc))
1845 self.assertTrue(re.search("Pipeline.*gate", desc))
1846 self.assertTrue(re.search("project-merge.*SUCCESS", desc))
1847 self.assertTrue(re.search("project-test1.*SUCCESS", desc))
1848 self.assertTrue(re.search("project-test2.*SUCCESS", desc))
1849 self.assertTrue(re.search("Reported result.*SUCCESS", desc))
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001850
James E. Blairc8a1e052014-02-25 09:29:26 -08001851 def test_queue_names(self):
1852 "Test shared change queue names"
1853 project1 = self.sched.layout.projects['org/project1']
1854 project2 = self.sched.layout.projects['org/project2']
1855 q1 = self.sched.layout.pipelines['gate'].getQueue(project1)
1856 q2 = self.sched.layout.pipelines['gate'].getQueue(project2)
1857 self.assertEqual(q1.name, 'integration')
1858 self.assertEqual(q2.name, 'integration')
1859
1860 self.config.set('zuul', 'layout_config',
1861 'tests/fixtures/layout-bad-queue.yaml')
1862 with testtools.ExpectedException(
1863 Exception, "More than one name assigned to change queue"):
1864 self.sched.reconfigure(self.config)
1865
James E. Blair64ed6f22013-07-10 14:07:23 -07001866 def test_queue_precedence(self):
1867 "Test that queue precedence works"
1868
1869 self.gearman_server.hold_jobs_in_queue = True
James E. Blair8de58bd2013-07-18 16:23:33 -07001870 self.worker.hold_jobs_in_build = True
James E. Blair64ed6f22013-07-10 14:07:23 -07001871 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1872 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1873 A.addApproval('CRVW', 2)
1874 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1875
1876 self.waitUntilSettled()
1877 self.gearman_server.hold_jobs_in_queue = False
1878 self.gearman_server.release()
1879 self.waitUntilSettled()
1880
James E. Blair8de58bd2013-07-18 16:23:33 -07001881 # Run one build at a time to ensure non-race order:
1882 for x in range(6):
1883 self.release(self.builds[0])
1884 self.waitUntilSettled()
1885 self.worker.hold_jobs_in_build = False
1886 self.waitUntilSettled()
1887
James E. Blair64ed6f22013-07-10 14:07:23 -07001888 self.log.debug(self.history)
1889 self.assertEqual(self.history[0].pipeline, 'gate')
1890 self.assertEqual(self.history[1].pipeline, 'check')
1891 self.assertEqual(self.history[2].pipeline, 'gate')
1892 self.assertEqual(self.history[3].pipeline, 'gate')
1893 self.assertEqual(self.history[4].pipeline, 'check')
1894 self.assertEqual(self.history[5].pipeline, 'check')
1895
Clark Boylana5edbe42014-06-03 16:39:10 -07001896 def test_json_status(self):
James E. Blair1843a552013-07-03 14:19:52 -07001897 "Test that we can retrieve JSON status info"
1898 self.worker.hold_jobs_in_build = True
1899 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1900 A.addApproval('CRVW', 2)
1901 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1902 self.waitUntilSettled()
1903
1904 port = self.webapp.server.socket.getsockname()[1]
1905
Yuriy Taradaya6d452f2014-04-16 12:36:20 +04001906 req = urllib2.Request("http://localhost:%s/status.json" % port)
Yuriy Taradaya6d452f2014-04-16 12:36:20 +04001907 f = urllib2.urlopen(req)
Clark Boylanaa4f2e72014-06-03 21:22:40 -07001908 headers = f.info()
1909 self.assertIn('Content-Length', headers)
1910 self.assertIn('Content-Type', headers)
1911 self.assertEqual(headers['Content-Type'],
1912 'application/json; charset=UTF-8')
1913 self.assertIn('Last-Modified', headers)
James E. Blair1843a552013-07-03 14:19:52 -07001914 data = f.read()
1915
1916 self.worker.hold_jobs_in_build = False
1917 self.worker.release()
1918 self.waitUntilSettled()
1919
1920 data = json.loads(data)
1921 status_jobs = set()
1922 for p in data['pipelines']:
1923 for q in p['change_queues']:
James E. Blairbfb8e042014-12-30 17:01:44 -08001924 if p['name'] in ['gate', 'conflict']:
Clark Boylanaf2476f2014-01-23 14:47:36 -08001925 self.assertEqual(q['window'], 20)
1926 else:
1927 self.assertEqual(q['window'], 0)
James E. Blair1843a552013-07-03 14:19:52 -07001928 for head in q['heads']:
1929 for change in head:
Clark Boylanaf2476f2014-01-23 14:47:36 -08001930 self.assertTrue(change['active'])
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001931 self.assertEqual(change['id'], '1,1')
James E. Blair1843a552013-07-03 14:19:52 -07001932 for job in change['jobs']:
1933 status_jobs.add(job['name'])
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001934 self.assertIn('project-merge', status_jobs)
1935 self.assertIn('project-test1', status_jobs)
1936 self.assertIn('project-test2', status_jobs)
James E. Blair1843a552013-07-03 14:19:52 -07001937
James E. Blairc3d428e2013-12-03 15:06:48 -08001938 def test_merging_queues(self):
1939 "Test that transitively-connected change queues are merged"
1940 self.config.set('zuul', 'layout_config',
1941 'tests/fixtures/layout-merge-queues.yaml')
1942 self.sched.reconfigure(self.config)
1943 self.assertEqual(len(self.sched.layout.pipelines['gate'].queues), 1)
1944
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001945 def test_node_label(self):
1946 "Test that a job runs on a specific node label"
James E. Blair1f4c2bb2013-04-26 08:40:46 -07001947 self.worker.registerFunction('build:node-project-test1:debian')
1948
1949 A = self.fake_gerrit.addFakeChange('org/node-project', 'master', 'A')
1950 A.addApproval('CRVW', 2)
1951 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1952 self.waitUntilSettled()
James E. Blair4ca985f2013-05-30 12:27:43 -07001953
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001954 self.assertIsNone(self.getJobFromHistory('node-project-merge').node)
1955 self.assertEqual(self.getJobFromHistory('node-project-test1').node,
1956 'debian')
1957 self.assertIsNone(self.getJobFromHistory('node-project-test2').node)
James E. Blaircdccd972013-07-01 12:10:22 -07001958
1959 def test_live_reconfiguration(self):
1960 "Test that live reconfiguration works"
1961 self.worker.hold_jobs_in_build = True
1962 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1963 A.addApproval('CRVW', 2)
1964 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1965 self.waitUntilSettled()
1966
1967 self.sched.reconfigure(self.config)
1968
1969 self.worker.hold_jobs_in_build = False
1970 self.worker.release()
1971 self.waitUntilSettled()
Monty Taylor98f0f3e2013-07-06 16:02:31 -04001972 self.assertEqual(self.getJobFromHistory('project-merge').result,
1973 'SUCCESS')
1974 self.assertEqual(self.getJobFromHistory('project-test1').result,
1975 'SUCCESS')
1976 self.assertEqual(self.getJobFromHistory('project-test2').result,
1977 'SUCCESS')
1978 self.assertEqual(A.data['status'], 'MERGED')
1979 self.assertEqual(A.reported, 2)
James E. Blair287c06d2013-07-24 10:39:30 -07001980
James E. Blaire712d9f2013-07-31 11:40:11 -07001981 def test_live_reconfiguration_functions(self):
1982 "Test live reconfiguration with a custom function"
1983 self.worker.registerFunction('build:node-project-test1:debian')
1984 self.worker.registerFunction('build:node-project-test1:wheezy')
1985 A = self.fake_gerrit.addFakeChange('org/node-project', 'master', 'A')
1986 A.addApproval('CRVW', 2)
1987 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
1988 self.waitUntilSettled()
1989
1990 self.assertIsNone(self.getJobFromHistory('node-project-merge').node)
1991 self.assertEqual(self.getJobFromHistory('node-project-test1').node,
1992 'debian')
1993 self.assertIsNone(self.getJobFromHistory('node-project-test2').node)
1994
1995 self.config.set('zuul', 'layout_config',
1996 'tests/fixtures/layout-live-'
1997 'reconfiguration-functions.yaml')
1998 self.sched.reconfigure(self.config)
1999 self.worker.build_history = []
2000
2001 B = self.fake_gerrit.addFakeChange('org/node-project', 'master', 'B')
2002 B.addApproval('CRVW', 2)
2003 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2004 self.waitUntilSettled()
2005
2006 self.assertIsNone(self.getJobFromHistory('node-project-merge').node)
2007 self.assertEqual(self.getJobFromHistory('node-project-test1').node,
2008 'wheezy')
2009 self.assertIsNone(self.getJobFromHistory('node-project-test2').node)
2010
James E. Blair287c06d2013-07-24 10:39:30 -07002011 def test_delayed_repo_init(self):
2012 self.config.set('zuul', 'layout_config',
2013 'tests/fixtures/layout-delayed-repo-init.yaml')
2014 self.sched.reconfigure(self.config)
2015
2016 self.init_repo("org/new-project")
2017 A = self.fake_gerrit.addFakeChange('org/new-project', 'master', 'A')
2018
2019 A.addApproval('CRVW', 2)
2020 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2021 self.waitUntilSettled()
2022 self.assertEqual(self.getJobFromHistory('project-merge').result,
2023 'SUCCESS')
2024 self.assertEqual(self.getJobFromHistory('project-test1').result,
2025 'SUCCESS')
2026 self.assertEqual(self.getJobFromHistory('project-test2').result,
2027 'SUCCESS')
2028 self.assertEqual(A.data['status'], 'MERGED')
2029 self.assertEqual(A.reported, 2)
James E. Blair63bb0ef2013-07-29 17:14:51 -07002030
Clark Boylan6dbbc482013-10-18 10:57:31 -07002031 def test_repo_deleted(self):
2032 self.config.set('zuul', 'layout_config',
2033 'tests/fixtures/layout-repo-deleted.yaml')
2034 self.sched.reconfigure(self.config)
2035
2036 self.init_repo("org/delete-project")
2037 A = self.fake_gerrit.addFakeChange('org/delete-project', 'master', 'A')
2038
2039 A.addApproval('CRVW', 2)
2040 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2041 self.waitUntilSettled()
2042 self.assertEqual(self.getJobFromHistory('project-merge').result,
2043 'SUCCESS')
2044 self.assertEqual(self.getJobFromHistory('project-test1').result,
2045 'SUCCESS')
2046 self.assertEqual(self.getJobFromHistory('project-test2').result,
2047 'SUCCESS')
2048 self.assertEqual(A.data['status'], 'MERGED')
2049 self.assertEqual(A.reported, 2)
2050
2051 # Delete org/new-project zuul repo. Should be recloned.
2052 shutil.rmtree(os.path.join(self.git_root, "org/delete-project"))
2053
2054 B = self.fake_gerrit.addFakeChange('org/delete-project', 'master', 'B')
2055
2056 B.addApproval('CRVW', 2)
2057 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2058 self.waitUntilSettled()
2059 self.assertEqual(self.getJobFromHistory('project-merge').result,
2060 'SUCCESS')
2061 self.assertEqual(self.getJobFromHistory('project-test1').result,
2062 'SUCCESS')
2063 self.assertEqual(self.getJobFromHistory('project-test2').result,
2064 'SUCCESS')
2065 self.assertEqual(B.data['status'], 'MERGED')
2066 self.assertEqual(B.reported, 2)
2067
James E. Blair63bb0ef2013-07-29 17:14:51 -07002068 def test_timer(self):
2069 "Test that a periodic job is triggered"
2070 self.worker.hold_jobs_in_build = True
2071 self.config.set('zuul', 'layout_config',
2072 'tests/fixtures/layout-timer.yaml')
2073 self.sched.reconfigure(self.config)
2074 self.registerJobs()
2075
Clark Boylan3ee090a2014-04-03 20:55:09 -07002076 # The pipeline triggers every second, so we should have seen
2077 # several by now.
2078 time.sleep(5)
James E. Blair63bb0ef2013-07-29 17:14:51 -07002079 self.waitUntilSettled()
Clark Boylan3ee090a2014-04-03 20:55:09 -07002080
2081 self.assertEqual(len(self.builds), 2)
2082
James E. Blair63bb0ef2013-07-29 17:14:51 -07002083 port = self.webapp.server.socket.getsockname()[1]
2084
2085 f = urllib.urlopen("http://localhost:%s/status.json" % port)
2086 data = f.read()
2087
2088 self.worker.hold_jobs_in_build = False
Clark Boylan3ee090a2014-04-03 20:55:09 -07002089 # Stop queuing timer triggered jobs so that the assertions
2090 # below don't race against more jobs being queued.
2091 self.config.set('zuul', 'layout_config',
2092 'tests/fixtures/layout-no-timer.yaml')
2093 self.sched.reconfigure(self.config)
2094 self.registerJobs()
James E. Blair63bb0ef2013-07-29 17:14:51 -07002095 self.worker.release()
2096 self.waitUntilSettled()
2097
2098 self.assertEqual(self.getJobFromHistory(
2099 'project-bitrot-stable-old').result, 'SUCCESS')
2100 self.assertEqual(self.getJobFromHistory(
2101 'project-bitrot-stable-older').result, 'SUCCESS')
2102
2103 data = json.loads(data)
2104 status_jobs = set()
2105 for p in data['pipelines']:
2106 for q in p['change_queues']:
2107 for head in q['heads']:
2108 for change in head:
Alex Gaynorddb9ef32013-09-16 21:04:58 -07002109 self.assertEqual(change['id'], None)
James E. Blair63bb0ef2013-07-29 17:14:51 -07002110 for job in change['jobs']:
2111 status_jobs.add(job['name'])
2112 self.assertIn('project-bitrot-stable-old', status_jobs)
2113 self.assertIn('project-bitrot-stable-older', status_jobs)
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002114
James E. Blair4f6033c2014-03-27 15:49:09 -07002115 def test_idle(self):
2116 "Test that frequent periodic jobs work"
2117 self.worker.hold_jobs_in_build = True
James E. Blair4f6033c2014-03-27 15:49:09 -07002118
Clark Boylan3ee090a2014-04-03 20:55:09 -07002119 for x in range(1, 3):
2120 # Test that timer triggers periodic jobs even across
2121 # layout config reloads.
2122 # Start timer trigger
2123 self.config.set('zuul', 'layout_config',
2124 'tests/fixtures/layout-idle.yaml')
2125 self.sched.reconfigure(self.config)
2126 self.registerJobs()
James E. Blair4f6033c2014-03-27 15:49:09 -07002127
Clark Boylan3ee090a2014-04-03 20:55:09 -07002128 # The pipeline triggers every second, so we should have seen
2129 # several by now.
2130 time.sleep(5)
2131 self.waitUntilSettled()
2132
2133 # Stop queuing timer triggered jobs so that the assertions
2134 # below don't race against more jobs being queued.
2135 self.config.set('zuul', 'layout_config',
2136 'tests/fixtures/layout-no-timer.yaml')
2137 self.sched.reconfigure(self.config)
2138 self.registerJobs()
2139
2140 self.assertEqual(len(self.builds), 2)
2141 self.worker.release('.*')
2142 self.waitUntilSettled()
2143 self.assertEqual(len(self.builds), 0)
2144 self.assertEqual(len(self.history), x * 2)
James E. Blair4f6033c2014-03-27 15:49:09 -07002145
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002146 def test_check_smtp_pool(self):
2147 self.config.set('zuul', 'layout_config',
2148 'tests/fixtures/layout-smtp.yaml')
2149 self.sched.reconfigure(self.config)
2150
2151 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2152 self.waitUntilSettled()
2153
2154 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2155 self.waitUntilSettled()
2156
James E. Blairff80a2f2013-12-27 13:24:06 -08002157 self.assertEqual(len(self.smtp_messages), 2)
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002158
2159 # A.messages only holds what FakeGerrit places in it. Thus we
2160 # work on the knowledge of what the first message should be as
2161 # it is only configured to go to SMTP.
2162
2163 self.assertEqual('zuul@example.com',
James E. Blairff80a2f2013-12-27 13:24:06 -08002164 self.smtp_messages[0]['from_email'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002165 self.assertEqual(['you@example.com'],
James E. Blairff80a2f2013-12-27 13:24:06 -08002166 self.smtp_messages[0]['to_email'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002167 self.assertEqual('Starting check jobs.',
James E. Blairff80a2f2013-12-27 13:24:06 -08002168 self.smtp_messages[0]['body'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002169
2170 self.assertEqual('zuul_from@example.com',
James E. Blairff80a2f2013-12-27 13:24:06 -08002171 self.smtp_messages[1]['from_email'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002172 self.assertEqual(['alternative_me@example.com'],
James E. Blairff80a2f2013-12-27 13:24:06 -08002173 self.smtp_messages[1]['to_email'])
Joshua Hesketh5fea8672013-08-19 17:32:01 +10002174 self.assertEqual(A.messages[0],
James E. Blairff80a2f2013-12-27 13:24:06 -08002175 self.smtp_messages[1]['body'])
James E. Blairad28e912013-11-27 10:43:22 -08002176
James E. Blaire5910202013-12-27 09:50:31 -08002177 def test_timer_smtp(self):
2178 "Test that a periodic job is triggered"
Clark Boylan3ee090a2014-04-03 20:55:09 -07002179 self.worker.hold_jobs_in_build = True
James E. Blaire5910202013-12-27 09:50:31 -08002180 self.config.set('zuul', 'layout_config',
2181 'tests/fixtures/layout-timer-smtp.yaml')
2182 self.sched.reconfigure(self.config)
2183 self.registerJobs()
2184
Clark Boylan3ee090a2014-04-03 20:55:09 -07002185 # The pipeline triggers every second, so we should have seen
2186 # several by now.
2187 time.sleep(5)
James E. Blaire5910202013-12-27 09:50:31 -08002188 self.waitUntilSettled()
2189
Clark Boylan3ee090a2014-04-03 20:55:09 -07002190 self.assertEqual(len(self.builds), 2)
2191 self.worker.release('.*')
2192 self.waitUntilSettled()
2193 self.assertEqual(len(self.history), 2)
2194
James E. Blaire5910202013-12-27 09:50:31 -08002195 self.assertEqual(self.getJobFromHistory(
2196 'project-bitrot-stable-old').result, 'SUCCESS')
2197 self.assertEqual(self.getJobFromHistory(
2198 'project-bitrot-stable-older').result, 'SUCCESS')
2199
James E. Blairff80a2f2013-12-27 13:24:06 -08002200 self.assertEqual(len(self.smtp_messages), 1)
James E. Blaire5910202013-12-27 09:50:31 -08002201
2202 # A.messages only holds what FakeGerrit places in it. Thus we
2203 # work on the knowledge of what the first message should be as
2204 # it is only configured to go to SMTP.
2205
2206 self.assertEqual('zuul_from@example.com',
James E. Blairff80a2f2013-12-27 13:24:06 -08002207 self.smtp_messages[0]['from_email'])
James E. Blaire5910202013-12-27 09:50:31 -08002208 self.assertEqual(['alternative_me@example.com'],
James E. Blairff80a2f2013-12-27 13:24:06 -08002209 self.smtp_messages[0]['to_email'])
James E. Blaire5910202013-12-27 09:50:31 -08002210 self.assertIn('Subject: Periodic check for org/project succeeded',
James E. Blairff80a2f2013-12-27 13:24:06 -08002211 self.smtp_messages[0]['headers'])
James E. Blaire5910202013-12-27 09:50:31 -08002212
Clark Boylan3ee090a2014-04-03 20:55:09 -07002213 # Stop queuing timer triggered jobs and let any that may have
2214 # queued through so that end of test assertions pass.
2215 self.config.set('zuul', 'layout_config',
2216 'tests/fixtures/layout-no-timer.yaml')
2217 self.sched.reconfigure(self.config)
2218 self.registerJobs()
James E. Blairf8058972014-08-15 16:09:16 -07002219 self.waitUntilSettled()
Clark Boylan3ee090a2014-04-03 20:55:09 -07002220 self.worker.release('.*')
2221 self.waitUntilSettled()
2222
James E. Blairad28e912013-11-27 10:43:22 -08002223 def test_client_enqueue(self):
2224 "Test that the RPC client can enqueue a change"
2225 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2226 A.addApproval('CRVW', 2)
2227 A.addApproval('APRV', 1)
2228
2229 client = zuul.rpcclient.RPCClient('127.0.0.1',
2230 self.gearman_server.port)
2231 r = client.enqueue(pipeline='gate',
2232 project='org/project',
2233 trigger='gerrit',
James E. Blair36658cf2013-12-06 17:53:48 -08002234 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08002235 self.waitUntilSettled()
2236 self.assertEqual(self.getJobFromHistory('project-merge').result,
2237 'SUCCESS')
2238 self.assertEqual(self.getJobFromHistory('project-test1').result,
2239 'SUCCESS')
2240 self.assertEqual(self.getJobFromHistory('project-test2').result,
2241 'SUCCESS')
2242 self.assertEqual(A.data['status'], 'MERGED')
2243 self.assertEqual(A.reported, 2)
2244 self.assertEqual(r, True)
2245
2246 def test_client_enqueue_negative(self):
2247 "Test that the RPC client returns errors"
2248 client = zuul.rpcclient.RPCClient('127.0.0.1',
2249 self.gearman_server.port)
2250 with testtools.ExpectedException(zuul.rpcclient.RPCFailure,
2251 "Invalid project"):
2252 r = client.enqueue(pipeline='gate',
2253 project='project-does-not-exist',
2254 trigger='gerrit',
James E. Blair36658cf2013-12-06 17:53:48 -08002255 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08002256 client.shutdown()
2257 self.assertEqual(r, False)
2258
2259 with testtools.ExpectedException(zuul.rpcclient.RPCFailure,
2260 "Invalid pipeline"):
2261 r = client.enqueue(pipeline='pipeline-does-not-exist',
2262 project='org/project',
2263 trigger='gerrit',
James E. Blair36658cf2013-12-06 17:53:48 -08002264 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08002265 client.shutdown()
2266 self.assertEqual(r, False)
2267
2268 with testtools.ExpectedException(zuul.rpcclient.RPCFailure,
2269 "Invalid trigger"):
2270 r = client.enqueue(pipeline='gate',
2271 project='org/project',
2272 trigger='trigger-does-not-exist',
James E. Blair36658cf2013-12-06 17:53:48 -08002273 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08002274 client.shutdown()
2275 self.assertEqual(r, False)
2276
2277 with testtools.ExpectedException(zuul.rpcclient.RPCFailure,
2278 "Invalid change"):
2279 r = client.enqueue(pipeline='gate',
2280 project='org/project',
2281 trigger='gerrit',
James E. Blair36658cf2013-12-06 17:53:48 -08002282 change='1,1')
James E. Blairad28e912013-11-27 10:43:22 -08002283 client.shutdown()
2284 self.assertEqual(r, False)
2285
2286 self.waitUntilSettled()
2287 self.assertEqual(len(self.history), 0)
2288 self.assertEqual(len(self.builds), 0)
James E. Blair36658cf2013-12-06 17:53:48 -08002289
2290 def test_client_promote(self):
2291 "Test that the RPC client can promote a change"
2292 self.worker.hold_jobs_in_build = True
2293 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2294 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2295 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
2296 A.addApproval('CRVW', 2)
2297 B.addApproval('CRVW', 2)
2298 C.addApproval('CRVW', 2)
2299
2300 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2301 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2302 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
2303
2304 self.waitUntilSettled()
2305
Sean Daguef39b9ca2014-01-10 21:34:35 -05002306 items = self.sched.layout.pipelines['gate'].getAllItems()
2307 enqueue_times = {}
2308 for item in items:
2309 enqueue_times[str(item.change)] = item.enqueue_time
2310
James E. Blair36658cf2013-12-06 17:53:48 -08002311 client = zuul.rpcclient.RPCClient('127.0.0.1',
2312 self.gearman_server.port)
2313 r = client.promote(pipeline='gate',
2314 change_ids=['2,1', '3,1'])
2315
Sean Daguef39b9ca2014-01-10 21:34:35 -05002316 # ensure that enqueue times are durable
2317 items = self.sched.layout.pipelines['gate'].getAllItems()
2318 for item in items:
2319 self.assertEqual(
2320 enqueue_times[str(item.change)], item.enqueue_time)
2321
James E. Blair78acec92014-02-06 07:11:32 -08002322 self.waitUntilSettled()
James E. Blair36658cf2013-12-06 17:53:48 -08002323 self.worker.release('.*-merge')
2324 self.waitUntilSettled()
2325 self.worker.release('.*-merge')
2326 self.waitUntilSettled()
2327 self.worker.release('.*-merge')
2328 self.waitUntilSettled()
2329
2330 self.assertEqual(len(self.builds), 6)
2331 self.assertEqual(self.builds[0].name, 'project-test1')
2332 self.assertEqual(self.builds[1].name, 'project-test2')
2333 self.assertEqual(self.builds[2].name, 'project-test1')
2334 self.assertEqual(self.builds[3].name, 'project-test2')
2335 self.assertEqual(self.builds[4].name, 'project-test1')
2336 self.assertEqual(self.builds[5].name, 'project-test2')
2337
2338 self.assertTrue(self.job_has_changes(self.builds[0], B))
2339 self.assertFalse(self.job_has_changes(self.builds[0], A))
2340 self.assertFalse(self.job_has_changes(self.builds[0], C))
2341
2342 self.assertTrue(self.job_has_changes(self.builds[2], B))
2343 self.assertTrue(self.job_has_changes(self.builds[2], C))
2344 self.assertFalse(self.job_has_changes(self.builds[2], A))
2345
2346 self.assertTrue(self.job_has_changes(self.builds[4], B))
2347 self.assertTrue(self.job_has_changes(self.builds[4], C))
2348 self.assertTrue(self.job_has_changes(self.builds[4], A))
2349
2350 self.worker.release()
2351 self.waitUntilSettled()
2352
2353 self.assertEqual(A.data['status'], 'MERGED')
2354 self.assertEqual(A.reported, 2)
2355 self.assertEqual(B.data['status'], 'MERGED')
2356 self.assertEqual(B.reported, 2)
2357 self.assertEqual(C.data['status'], 'MERGED')
2358 self.assertEqual(C.reported, 2)
2359
2360 client.shutdown()
2361 self.assertEqual(r, True)
2362
2363 def test_client_promote_dependent(self):
2364 "Test that the RPC client can promote a dependent change"
2365 # C (depends on B) -> B -> A ; then promote C to get:
2366 # A -> C (depends on B) -> B
2367 self.worker.hold_jobs_in_build = True
2368 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2369 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2370 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
2371
2372 C.setDependsOn(B, 1)
2373
2374 A.addApproval('CRVW', 2)
2375 B.addApproval('CRVW', 2)
2376 C.addApproval('CRVW', 2)
2377
2378 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2379 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2380 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
2381
2382 self.waitUntilSettled()
2383
2384 client = zuul.rpcclient.RPCClient('127.0.0.1',
2385 self.gearman_server.port)
2386 r = client.promote(pipeline='gate',
2387 change_ids=['3,1'])
2388
James E. Blair78acec92014-02-06 07:11:32 -08002389 self.waitUntilSettled()
James E. Blair36658cf2013-12-06 17:53:48 -08002390 self.worker.release('.*-merge')
2391 self.waitUntilSettled()
2392 self.worker.release('.*-merge')
2393 self.waitUntilSettled()
2394 self.worker.release('.*-merge')
2395 self.waitUntilSettled()
2396
2397 self.assertEqual(len(self.builds), 6)
2398 self.assertEqual(self.builds[0].name, 'project-test1')
2399 self.assertEqual(self.builds[1].name, 'project-test2')
2400 self.assertEqual(self.builds[2].name, 'project-test1')
2401 self.assertEqual(self.builds[3].name, 'project-test2')
2402 self.assertEqual(self.builds[4].name, 'project-test1')
2403 self.assertEqual(self.builds[5].name, 'project-test2')
2404
2405 self.assertTrue(self.job_has_changes(self.builds[0], B))
2406 self.assertFalse(self.job_has_changes(self.builds[0], A))
2407 self.assertFalse(self.job_has_changes(self.builds[0], C))
2408
2409 self.assertTrue(self.job_has_changes(self.builds[2], B))
2410 self.assertTrue(self.job_has_changes(self.builds[2], C))
2411 self.assertFalse(self.job_has_changes(self.builds[2], A))
2412
2413 self.assertTrue(self.job_has_changes(self.builds[4], B))
2414 self.assertTrue(self.job_has_changes(self.builds[4], C))
2415 self.assertTrue(self.job_has_changes(self.builds[4], A))
2416
2417 self.worker.release()
2418 self.waitUntilSettled()
2419
2420 self.assertEqual(A.data['status'], 'MERGED')
2421 self.assertEqual(A.reported, 2)
2422 self.assertEqual(B.data['status'], 'MERGED')
2423 self.assertEqual(B.reported, 2)
2424 self.assertEqual(C.data['status'], 'MERGED')
2425 self.assertEqual(C.reported, 2)
2426
2427 client.shutdown()
2428 self.assertEqual(r, True)
2429
2430 def test_client_promote_negative(self):
2431 "Test that the RPC client returns errors for promotion"
2432 self.worker.hold_jobs_in_build = True
2433 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2434 A.addApproval('CRVW', 2)
2435 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2436 self.waitUntilSettled()
2437
2438 client = zuul.rpcclient.RPCClient('127.0.0.1',
2439 self.gearman_server.port)
2440
2441 with testtools.ExpectedException(zuul.rpcclient.RPCFailure):
2442 r = client.promote(pipeline='nonexistent',
2443 change_ids=['2,1', '3,1'])
2444 client.shutdown()
2445 self.assertEqual(r, False)
2446
2447 with testtools.ExpectedException(zuul.rpcclient.RPCFailure):
2448 r = client.promote(pipeline='gate',
2449 change_ids=['4,1'])
2450 client.shutdown()
2451 self.assertEqual(r, False)
2452
2453 self.worker.hold_jobs_in_build = False
2454 self.worker.release()
2455 self.waitUntilSettled()
Clark Boylan7603a372014-01-21 11:43:20 -08002456
2457 def test_queue_rate_limiting(self):
2458 "Test that DependentPipelines are rate limited with dep across window"
2459 self.config.set('zuul', 'layout_config',
2460 'tests/fixtures/layout-rate-limit.yaml')
2461 self.sched.reconfigure(self.config)
2462 self.worker.hold_jobs_in_build = True
2463 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2464 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2465 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
2466
2467 C.setDependsOn(B, 1)
2468 self.worker.addFailTest('project-test1', A)
2469
2470 A.addApproval('CRVW', 2)
2471 B.addApproval('CRVW', 2)
2472 C.addApproval('CRVW', 2)
2473
2474 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2475 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2476 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
2477 self.waitUntilSettled()
2478
2479 # Only A and B will have their merge jobs queued because
2480 # window is 2.
2481 self.assertEqual(len(self.builds), 2)
2482 self.assertEqual(self.builds[0].name, 'project-merge')
2483 self.assertEqual(self.builds[1].name, 'project-merge')
2484
2485 self.worker.release('.*-merge')
2486 self.waitUntilSettled()
2487 self.worker.release('.*-merge')
2488 self.waitUntilSettled()
2489
2490 # Only A and B will have their test jobs queued because
2491 # window is 2.
2492 self.assertEqual(len(self.builds), 4)
2493 self.assertEqual(self.builds[0].name, 'project-test1')
2494 self.assertEqual(self.builds[1].name, 'project-test2')
2495 self.assertEqual(self.builds[2].name, 'project-test1')
2496 self.assertEqual(self.builds[3].name, 'project-test2')
2497
2498 self.worker.release('project-.*')
2499 self.waitUntilSettled()
2500
2501 queue = self.sched.layout.pipelines['gate'].queues[0]
2502 # A failed so window is reduced by 1 to 1.
2503 self.assertEqual(queue.window, 1)
2504 self.assertEqual(queue.window_floor, 1)
2505 self.assertEqual(A.data['status'], 'NEW')
2506
2507 # Gate is reset and only B's merge job is queued because
2508 # window shrunk to 1.
2509 self.assertEqual(len(self.builds), 1)
2510 self.assertEqual(self.builds[0].name, 'project-merge')
2511
2512 self.worker.release('.*-merge')
2513 self.waitUntilSettled()
2514
2515 # Only B's test jobs are queued because window is still 1.
2516 self.assertEqual(len(self.builds), 2)
2517 self.assertEqual(self.builds[0].name, 'project-test1')
2518 self.assertEqual(self.builds[1].name, 'project-test2')
2519
2520 self.worker.release('project-.*')
2521 self.waitUntilSettled()
2522
2523 # B was successfully merged so window is increased to 2.
2524 self.assertEqual(queue.window, 2)
2525 self.assertEqual(queue.window_floor, 1)
2526 self.assertEqual(B.data['status'], 'MERGED')
2527
2528 # Only C is left and its merge job is queued.
2529 self.assertEqual(len(self.builds), 1)
2530 self.assertEqual(self.builds[0].name, 'project-merge')
2531
2532 self.worker.release('.*-merge')
2533 self.waitUntilSettled()
2534
2535 # After successful merge job the test jobs for C are queued.
2536 self.assertEqual(len(self.builds), 2)
2537 self.assertEqual(self.builds[0].name, 'project-test1')
2538 self.assertEqual(self.builds[1].name, 'project-test2')
2539
2540 self.worker.release('project-.*')
2541 self.waitUntilSettled()
2542
2543 # C successfully merged so window is bumped to 3.
2544 self.assertEqual(queue.window, 3)
2545 self.assertEqual(queue.window_floor, 1)
2546 self.assertEqual(C.data['status'], 'MERGED')
2547
2548 def test_queue_rate_limiting_dependent(self):
2549 "Test that DependentPipelines are rate limited with dep in window"
2550 self.config.set('zuul', 'layout_config',
2551 'tests/fixtures/layout-rate-limit.yaml')
2552 self.sched.reconfigure(self.config)
2553 self.worker.hold_jobs_in_build = True
2554 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2555 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2556 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
2557
2558 B.setDependsOn(A, 1)
2559
2560 self.worker.addFailTest('project-test1', A)
2561
2562 A.addApproval('CRVW', 2)
2563 B.addApproval('CRVW', 2)
2564 C.addApproval('CRVW', 2)
2565
2566 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2567 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2568 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
2569 self.waitUntilSettled()
2570
2571 # Only A and B will have their merge jobs queued because
2572 # window is 2.
2573 self.assertEqual(len(self.builds), 2)
2574 self.assertEqual(self.builds[0].name, 'project-merge')
2575 self.assertEqual(self.builds[1].name, 'project-merge')
2576
2577 self.worker.release('.*-merge')
2578 self.waitUntilSettled()
2579 self.worker.release('.*-merge')
2580 self.waitUntilSettled()
2581
2582 # Only A and B will have their test jobs queued because
2583 # window is 2.
2584 self.assertEqual(len(self.builds), 4)
2585 self.assertEqual(self.builds[0].name, 'project-test1')
2586 self.assertEqual(self.builds[1].name, 'project-test2')
2587 self.assertEqual(self.builds[2].name, 'project-test1')
2588 self.assertEqual(self.builds[3].name, 'project-test2')
2589
2590 self.worker.release('project-.*')
2591 self.waitUntilSettled()
2592
2593 queue = self.sched.layout.pipelines['gate'].queues[0]
2594 # A failed so window is reduced by 1 to 1.
2595 self.assertEqual(queue.window, 1)
2596 self.assertEqual(queue.window_floor, 1)
2597 self.assertEqual(A.data['status'], 'NEW')
2598 self.assertEqual(B.data['status'], 'NEW')
2599
2600 # Gate is reset and only C's merge job is queued because
2601 # window shrunk to 1 and A and B were dequeued.
2602 self.assertEqual(len(self.builds), 1)
2603 self.assertEqual(self.builds[0].name, 'project-merge')
2604
2605 self.worker.release('.*-merge')
2606 self.waitUntilSettled()
2607
2608 # Only C's test jobs are queued because window is still 1.
2609 self.assertEqual(len(self.builds), 2)
2610 self.assertEqual(self.builds[0].name, 'project-test1')
2611 self.assertEqual(self.builds[1].name, 'project-test2')
2612
2613 self.worker.release('project-.*')
2614 self.waitUntilSettled()
2615
2616 # C was successfully merged so window is increased to 2.
2617 self.assertEqual(queue.window, 2)
2618 self.assertEqual(queue.window_floor, 1)
2619 self.assertEqual(C.data['status'], 'MERGED')
Joshua Heskethba8776a2014-01-12 14:35:40 +08002620
2621 def test_worker_update_metadata(self):
2622 "Test if a worker can send back metadata about itself"
2623 self.worker.hold_jobs_in_build = True
2624
2625 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2626 A.addApproval('CRVW', 2)
2627 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2628 self.waitUntilSettled()
2629
2630 self.assertEqual(len(self.launcher.builds), 1)
2631
2632 self.log.debug('Current builds:')
2633 self.log.debug(self.launcher.builds)
2634
2635 start = time.time()
2636 while True:
2637 if time.time() - start > 10:
2638 raise Exception("Timeout waiting for gearman server to report "
2639 + "back to the client")
2640 build = self.launcher.builds.values()[0]
2641 if build.worker.name == "My Worker":
2642 break
2643 else:
2644 time.sleep(0)
2645
2646 self.log.debug(build)
2647 self.assertEqual("My Worker", build.worker.name)
2648 self.assertEqual("localhost", build.worker.hostname)
2649 self.assertEqual(['127.0.0.1', '192.168.1.1'], build.worker.ips)
2650 self.assertEqual("zuul.example.org", build.worker.fqdn)
2651 self.assertEqual("FakeBuilder", build.worker.program)
2652 self.assertEqual("v1.1", build.worker.version)
2653 self.assertEqual({'something': 'else'}, build.worker.extra)
2654
2655 self.worker.hold_jobs_in_build = False
2656 self.worker.release()
2657 self.waitUntilSettled()
Joshua Hesketh3979e3e2014-03-04 11:21:10 +11002658
2659 def test_footer_message(self):
2660 "Test a pipeline's footer message is correctly added to the report."
2661 self.config.set('zuul', 'layout_config',
2662 'tests/fixtures/layout-footer-message.yaml')
2663 self.sched.reconfigure(self.config)
2664 self.registerJobs()
2665
2666 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2667 A.addApproval('CRVW', 2)
2668 self.worker.addFailTest('test1', A)
2669 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2670 self.waitUntilSettled()
2671
2672 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2673 B.addApproval('CRVW', 2)
2674 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2675 self.waitUntilSettled()
2676
2677 self.assertEqual(2, len(self.smtp_messages))
2678
2679 failure_body = """\
2680Build failed. For information on how to proceed, see \
2681http://wiki.example.org/Test_Failures
2682
2683- test1 http://logs.example.com/1/1/gate/test1/0 : FAILURE in 0s
2684- test2 http://logs.example.com/1/1/gate/test2/1 : SUCCESS in 0s
2685
2686For CI problems and help debugging, contact ci@example.org"""
2687
2688 success_body = """\
2689Build succeeded.
2690
2691- test1 http://logs.example.com/2/1/gate/test1/2 : SUCCESS in 0s
2692- test2 http://logs.example.com/2/1/gate/test2/3 : SUCCESS in 0s
2693
2694For CI problems and help debugging, contact ci@example.org"""
2695
2696 self.assertEqual(failure_body, self.smtp_messages[0]['body'])
2697 self.assertEqual(success_body, self.smtp_messages[1]['body'])
Joshua Heskethb7179772014-01-30 23:30:46 +11002698
2699 def test_merge_failure_reporters(self):
2700 """Check that the config is set up correctly"""
2701
2702 self.config.set('zuul', 'layout_config',
2703 'tests/fixtures/layout-merge-failure.yaml')
2704 self.sched.reconfigure(self.config)
2705 self.registerJobs()
2706
2707 self.assertEqual(
2708 "Merge Failed.\n\nThis change was unable to be automatically "
2709 "merged with the current state of the repository. Please rebase "
2710 "your change and upload a new patchset.",
2711 self.sched.layout.pipelines['check'].merge_failure_message)
2712 self.assertEqual(
2713 "The merge failed! For more information...",
2714 self.sched.layout.pipelines['gate'].merge_failure_message)
2715
2716 self.assertEqual(
2717 len(self.sched.layout.pipelines['check'].merge_failure_actions), 1)
2718 self.assertEqual(
2719 len(self.sched.layout.pipelines['gate'].merge_failure_actions), 2)
2720
2721 self.assertTrue(isinstance(
2722 self.sched.layout.pipelines['check'].merge_failure_actions[0].
2723 reporter, zuul.reporter.gerrit.Reporter))
2724
2725 self.assertTrue(
2726 (
2727 isinstance(self.sched.layout.pipelines['gate'].
2728 merge_failure_actions[0].reporter,
2729 zuul.reporter.smtp.Reporter) and
2730 isinstance(self.sched.layout.pipelines['gate'].
2731 merge_failure_actions[1].reporter,
2732 zuul.reporter.gerrit.Reporter)
2733 ) or (
2734 isinstance(self.sched.layout.pipelines['gate'].
2735 merge_failure_actions[0].reporter,
2736 zuul.reporter.gerrit.Reporter) and
2737 isinstance(self.sched.layout.pipelines['gate'].
2738 merge_failure_actions[1].reporter,
2739 zuul.reporter.smtp.Reporter)
2740 )
2741 )
2742
2743 def test_merge_failure_reports(self):
2744 """Check that when a change fails to merge the correct message is sent
2745 to the correct reporter"""
2746 self.config.set('zuul', 'layout_config',
2747 'tests/fixtures/layout-merge-failure.yaml')
2748 self.sched.reconfigure(self.config)
2749 self.registerJobs()
2750
2751 # Check a test failure isn't reported to SMTP
2752 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2753 A.addApproval('CRVW', 2)
2754 self.worker.addFailTest('project-test1', A)
2755 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2756 self.waitUntilSettled()
2757
2758 self.assertEqual(3, len(self.history)) # 3 jobs
2759 self.assertEqual(0, len(self.smtp_messages))
2760
2761 # Check a merge failure is reported to SMTP
2762 # B should be merged, but C will conflict with B
2763 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2764 B.addPatchset(['conflict'])
2765 C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
2766 C.addPatchset(['conflict'])
2767 B.addApproval('CRVW', 2)
2768 C.addApproval('CRVW', 2)
2769 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2770 self.fake_gerrit.addEvent(C.addApproval('APRV', 1))
2771 self.waitUntilSettled()
2772
2773 self.assertEqual(6, len(self.history)) # A and B jobs
2774 self.assertEqual(1, len(self.smtp_messages))
2775 self.assertEqual('The merge failed! For more information...',
2776 self.smtp_messages[0]['body'])
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11002777
2778 def test_swift_instructions(self):
2779 "Test that the correct swift instructions are sent to the workers"
2780 self.config.set('zuul', 'layout_config',
2781 'tests/fixtures/layout-swift.yaml')
2782 self.sched.reconfigure(self.config)
2783 self.registerJobs()
2784
2785 self.worker.hold_jobs_in_build = True
2786 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2787
2788 A.addApproval('CRVW', 2)
2789 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2790 self.waitUntilSettled()
2791
2792 self.assertEqual(
2793 "https://storage.example.org/V1/AUTH_account/merge_logs/1/1/1/"
2794 "gate/test-merge/",
Joshua Hesketh76dee532014-07-03 15:39:13 +10002795 self.builds[0].parameters['SWIFT_logs_URL'][:-7])
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11002796 self.assertEqual(5,
2797 len(self.builds[0].parameters['SWIFT_logs_HMAC_BODY'].
2798 split('\n')))
2799 self.assertIn('SWIFT_logs_SIGNATURE', self.builds[0].parameters)
2800
2801 self.assertEqual(
2802 "https://storage.example.org/V1/AUTH_account/logs/1/1/1/"
2803 "gate/test-test/",
Joshua Hesketh76dee532014-07-03 15:39:13 +10002804 self.builds[1].parameters['SWIFT_logs_URL'][:-7])
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11002805 self.assertEqual(5,
2806 len(self.builds[1].parameters['SWIFT_logs_HMAC_BODY'].
2807 split('\n')))
2808 self.assertIn('SWIFT_logs_SIGNATURE', self.builds[1].parameters)
2809
2810 self.assertEqual(
2811 "https://storage.example.org/V1/AUTH_account/stash/1/1/1/"
2812 "gate/test-test/",
Joshua Hesketh76dee532014-07-03 15:39:13 +10002813 self.builds[1].parameters['SWIFT_MOSTLY_URL'][:-7])
Joshua Hesketh36c3fa52014-01-22 11:40:52 +11002814 self.assertEqual(5,
2815 len(self.builds[1].
2816 parameters['SWIFT_MOSTLY_HMAC_BODY'].split('\n')))
2817 self.assertIn('SWIFT_MOSTLY_SIGNATURE', self.builds[1].parameters)
2818
2819 self.worker.hold_jobs_in_build = False
2820 self.worker.release()
2821 self.waitUntilSettled()
Joshua Hesketh85af4e92014-02-21 08:28:58 -08002822
2823 def test_client_get_running_jobs(self):
2824 "Test that the RPC client can get a list of running jobs"
2825 self.worker.hold_jobs_in_build = True
2826 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2827 A.addApproval('CRVW', 2)
2828 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2829 self.waitUntilSettled()
2830
2831 client = zuul.rpcclient.RPCClient('127.0.0.1',
2832 self.gearman_server.port)
2833
2834 # Wait for gearman server to send the initial workData back to zuul
2835 start = time.time()
2836 while True:
2837 if time.time() - start > 10:
2838 raise Exception("Timeout waiting for gearman server to report "
2839 + "back to the client")
2840 build = self.launcher.builds.values()[0]
2841 if build.worker.name == "My Worker":
2842 break
2843 else:
2844 time.sleep(0)
2845
2846 running_items = client.get_running_jobs()
2847
2848 self.assertEqual(1, len(running_items))
2849 running_item = running_items[0]
2850 self.assertEqual([], running_item['failing_reasons'])
2851 self.assertEqual([], running_item['items_behind'])
2852 self.assertEqual('https://hostname/1', running_item['url'])
2853 self.assertEqual(None, running_item['item_ahead'])
2854 self.assertEqual('org/project', running_item['project'])
2855 self.assertEqual(None, running_item['remaining_time'])
2856 self.assertEqual(True, running_item['active'])
2857 self.assertEqual('1,1', running_item['id'])
2858
2859 self.assertEqual(3, len(running_item['jobs']))
2860 for job in running_item['jobs']:
2861 if job['name'] == 'project-merge':
2862 self.assertEqual('project-merge', job['name'])
2863 self.assertEqual('gate', job['pipeline'])
2864 self.assertEqual(False, job['retry'])
2865 self.assertEqual(13, len(job['parameters']))
2866 self.assertEqual('https://server/job/project-merge/0/',
2867 job['url'])
2868 self.assertEqual(7, len(job['worker']))
2869 self.assertEqual(False, job['canceled'])
2870 self.assertEqual(True, job['voting'])
2871 self.assertEqual(None, job['result'])
2872 self.assertEqual('gate', job['pipeline'])
2873 break
2874
2875 self.worker.hold_jobs_in_build = False
2876 self.worker.release()
2877 self.waitUntilSettled()
2878
2879 running_items = client.get_running_jobs()
2880 self.assertEqual(0, len(running_items))
James E. Blairbadc1ad2014-04-28 13:55:14 -07002881
2882 def test_nonvoting_pipeline(self):
2883 "Test that a nonvoting pipeline (experimental) can still report"
2884
Joshua Heskethcc017ea2014-04-30 19:55:25 +10002885 A = self.fake_gerrit.addFakeChange('org/experimental-project',
2886 'master', 'A')
James E. Blairbadc1ad2014-04-28 13:55:14 -07002887 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2888 self.waitUntilSettled()
Joshua Heskethcc017ea2014-04-30 19:55:25 +10002889 self.assertEqual(
2890 self.getJobFromHistory('experimental-project-test').result,
2891 'SUCCESS')
James E. Blairbadc1ad2014-04-28 13:55:14 -07002892 self.assertEqual(A.reported, 1)
James E. Blair5ee24252014-12-30 10:12:29 -08002893
2894 def test_crd_gate(self):
2895 "Test cross-repo dependencies"
2896 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
2897 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
2898 A.addApproval('CRVW', 2)
2899 B.addApproval('CRVW', 2)
2900
2901 AM2 = self.fake_gerrit.addFakeChange('org/project1', 'master', 'AM2')
2902 AM1 = self.fake_gerrit.addFakeChange('org/project1', 'master', 'AM1')
2903 AM2.setMerged()
2904 AM1.setMerged()
2905
2906 BM2 = self.fake_gerrit.addFakeChange('org/project2', 'master', 'BM2')
2907 BM1 = self.fake_gerrit.addFakeChange('org/project2', 'master', 'BM1')
2908 BM2.setMerged()
2909 BM1.setMerged()
2910
2911 # A -> AM1 -> AM2
2912 # B -> BM1 -> BM2
2913 # A Depends-On: B
2914 # M2 is here to make sure it is never queried. If it is, it
2915 # means zuul is walking down the entire history of merged
2916 # changes.
2917
2918 B.setDependsOn(BM1, 1)
2919 BM1.setDependsOn(BM2, 1)
2920
2921 A.setDependsOn(AM1, 1)
2922 AM1.setDependsOn(AM2, 1)
2923
2924 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
2925 A.subject, B.data['id'])
2926
2927 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2928 self.waitUntilSettled()
2929
2930 self.assertEqual(A.data['status'], 'NEW')
2931 self.assertEqual(B.data['status'], 'NEW')
2932
2933 source = self.sched.layout.pipelines['gate'].source
2934 source.maintainCache([])
2935
2936 self.worker.hold_jobs_in_build = True
2937 B.addApproval('APRV', 1)
2938 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2939 self.waitUntilSettled()
2940
2941 self.worker.release('.*-merge')
2942 self.waitUntilSettled()
2943 self.worker.release('.*-merge')
2944 self.waitUntilSettled()
2945 self.worker.hold_jobs_in_build = False
2946 self.worker.release()
2947 self.waitUntilSettled()
2948
2949 self.assertEqual(AM2.queried, 0)
2950 self.assertEqual(BM2.queried, 0)
2951 self.assertEqual(A.data['status'], 'MERGED')
2952 self.assertEqual(B.data['status'], 'MERGED')
2953 self.assertEqual(A.reported, 2)
2954 self.assertEqual(B.reported, 2)
2955
2956 self.assertEqual(self.history[-1].changes, '2,1 1,1')
2957
2958 def test_crd_unshared_gate(self):
2959 "Test cross-repo dependencies in unshared gate queues"
2960 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
2961 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2962 A.addApproval('CRVW', 2)
2963 B.addApproval('CRVW', 2)
2964
2965 # A Depends-On: B
2966 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
2967 A.subject, B.data['id'])
2968
2969 # A and B do not share a queue, make sure that A is unable to
2970 # enqueue B (and therefore, A is unable to be enqueued).
2971 B.addApproval('APRV', 1)
2972 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2973 self.waitUntilSettled()
2974
2975 self.assertEqual(A.data['status'], 'NEW')
2976 self.assertEqual(B.data['status'], 'NEW')
2977 self.assertEqual(A.reported, 0)
2978 self.assertEqual(B.reported, 0)
2979 self.assertEqual(len(self.history), 0)
2980
2981 # Enqueue and merge B alone.
2982 self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
2983 self.waitUntilSettled()
2984
2985 self.assertEqual(B.data['status'], 'MERGED')
2986 self.assertEqual(B.reported, 2)
2987
2988 # Now that B is merged, A should be able to be enqueued and
2989 # merged.
2990 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
2991 self.waitUntilSettled()
2992
2993 self.assertEqual(A.data['status'], 'MERGED')
2994 self.assertEqual(A.reported, 2)
2995
2996 def test_crd_cycle(self):
2997 "Test cross-repo dependency cycles"
2998 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
2999 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3000 A.addApproval('CRVW', 2)
3001 B.addApproval('CRVW', 2)
3002
3003 # A -> B -> A (via commit-depends)
3004
3005 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3006 A.subject, B.data['id'])
3007 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3008 B.subject, A.data['id'])
3009
3010 self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
3011 self.waitUntilSettled()
3012
3013 self.assertEqual(A.reported, 0)
3014 self.assertEqual(B.reported, 0)
3015 self.assertEqual(A.data['status'], 'NEW')
3016 self.assertEqual(B.data['status'], 'NEW')
James E. Blairbfb8e042014-12-30 17:01:44 -08003017
3018 def test_crd_check(self):
3019 "Test cross-repo dependencies in independent pipelines"
3020
3021 self.gearman_server.hold_jobs_in_queue = True
3022 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
3023 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
3024
3025 # A Depends-On: B
3026 A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
3027 A.subject, B.data['id'])
3028
3029 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3030 self.waitUntilSettled()
3031
3032 queue = self.gearman_server.getQueue()
3033 ref = self.getParameter(queue[-1], 'ZUUL_REF')
3034 self.gearman_server.hold_jobs_in_queue = False
3035 self.gearman_server.release()
3036 self.waitUntilSettled()
3037
3038 path = os.path.join(self.git_root, "org/project1")
3039 repo = git.Repo(path)
3040 repo_messages = [c.message.strip() for c in repo.iter_commits(ref)]
3041 repo_messages.reverse()
3042 correct_messages = ['initial commit', 'A-1']
3043 self.assertEqual(repo_messages, correct_messages)
3044
3045 path = os.path.join(self.git_root, "org/project2")
3046 repo = git.Repo(path)
3047 repo_messages = [c.message.strip() for c in repo.iter_commits(ref)]
3048 repo_messages.reverse()
3049 correct_messages = ['initial commit', 'B-1']
3050 self.assertEqual(repo_messages, correct_messages)
3051
3052 self.assertEqual(A.data['status'], 'NEW')
3053 self.assertEqual(B.data['status'], 'NEW')
3054 self.assertEqual(A.reported, 1)
3055 self.assertEqual(B.reported, 0)
3056
3057 self.assertEqual(self.history[0].changes, '2,1 1,1')
3058 self.assertEqual(len(self.sched.layout.pipelines['check'].queues), 0)