blob: 3ae56ad07dd26d786d16575969ec9e4c16fefe3a [file] [log] [blame]
James E. Blair9c17dbf2014-06-23 14:21:58 -07001#!/usr/bin/env python
2
3# Copyright 2012-2014 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
17import logging
18import time
19
20from tests.base import ZuulTestCase
21
22logging.basicConfig(level=logging.DEBUG,
23 format='%(asctime)s %(name)-32s '
24 '%(levelname)-8s %(message)s')
25
26
27class TestRequirements(ZuulTestCase):
28 """Test pipeline and trigger requirements"""
29
30 def test_pipeline_require_approval_newer_than(self):
31 "Test pipeline requirement: approval newer than"
32 return self._test_require_approval_newer_than('org/project1',
33 'project1-pipeline')
34
35 def test_trigger_require_approval_newer_than(self):
36 "Test trigger requirement: approval newer than"
37 return self._test_require_approval_newer_than('org/project2',
38 'project2-trigger')
39
40 def _test_require_approval_newer_than(self, project, job):
41 self.config.set('zuul', 'layout_config',
42 'tests/fixtures/layout-requirement-newer-than.yaml')
43 self.sched.reconfigure(self.config)
44 self.registerJobs()
45
46 A = self.fake_gerrit.addFakeChange(project, 'master', 'A')
47 # A comment event that we will keep submitting to trigger
48 comment = A.addApproval('CRVW', 2, username='nobody')
49 self.fake_gerrit.addEvent(comment)
50 self.waitUntilSettled()
51 # No +1 from Jenkins so should not be enqueued
52 self.assertEqual(len(self.history), 0)
53
54 # Add a too-old +1, should not be enqueued
Joshua Hesketh642824b2014-07-01 17:54:59 +100055 A.addApproval('VRFY', 1, username='jenkins',
56 granted_on=time.time() - 72 * 60 * 60)
James E. Blair9c17dbf2014-06-23 14:21:58 -070057 self.fake_gerrit.addEvent(comment)
58 self.waitUntilSettled()
59 self.assertEqual(len(self.history), 0)
60
61 # Add a recent +1
Joshua Hesketh642824b2014-07-01 17:54:59 +100062 self.fake_gerrit.addEvent(A.addApproval('VRFY', 1, username='jenkins'))
James E. Blair9c17dbf2014-06-23 14:21:58 -070063 self.fake_gerrit.addEvent(comment)
64 self.waitUntilSettled()
65 self.assertEqual(len(self.history), 1)
66 self.assertEqual(self.history[0].name, job)
67
68 def test_pipeline_require_approval_older_than(self):
69 "Test pipeline requirement: approval older than"
70 return self._test_require_approval_older_than('org/project1',
71 'project1-pipeline')
72
73 def test_trigger_require_approval_older_than(self):
74 "Test trigger requirement: approval older than"
75 return self._test_require_approval_older_than('org/project2',
76 'project2-trigger')
77
78 def _test_require_approval_older_than(self, project, job):
79 self.config.set('zuul', 'layout_config',
80 'tests/fixtures/layout-requirement-older-than.yaml')
81 self.sched.reconfigure(self.config)
82 self.registerJobs()
83
84 A = self.fake_gerrit.addFakeChange(project, 'master', 'A')
85 # A comment event that we will keep submitting to trigger
86 comment = A.addApproval('CRVW', 2, username='nobody')
87 self.fake_gerrit.addEvent(comment)
88 self.waitUntilSettled()
89 # No +1 from Jenkins so should not be enqueued
90 self.assertEqual(len(self.history), 0)
91
92 # Add a recent +1 which should not be enqueued
93 A.addApproval('VRFY', 1)
94 self.fake_gerrit.addEvent(comment)
95 self.waitUntilSettled()
96 self.assertEqual(len(self.history), 0)
97
98 # Add an old +1 which should be enqueued
Joshua Hesketh642824b2014-07-01 17:54:59 +100099 A.addApproval('VRFY', 1, username='jenkins',
100 granted_on=time.time() - 72 * 60 * 60)
James E. Blair9c17dbf2014-06-23 14:21:58 -0700101 self.fake_gerrit.addEvent(comment)
102 self.waitUntilSettled()
103 self.assertEqual(len(self.history), 1)
104 self.assertEqual(self.history[0].name, job)
105
106 def test_pipeline_require_approval_username(self):
107 "Test pipeline requirement: approval username"
108 return self._test_require_approval_username('org/project1',
109 'project1-pipeline')
110
111 def test_trigger_require_approval_username(self):
112 "Test trigger requirement: approval username"
113 return self._test_require_approval_username('org/project2',
114 'project2-trigger')
115
116 def _test_require_approval_username(self, project, job):
117 self.config.set('zuul', 'layout_config',
118 'tests/fixtures/layout-requirement-username.yaml')
119 self.sched.reconfigure(self.config)
120 self.registerJobs()
121
122 A = self.fake_gerrit.addFakeChange(project, 'master', 'A')
123 # A comment event that we will keep submitting to trigger
124 comment = A.addApproval('CRVW', 2, username='nobody')
125 self.fake_gerrit.addEvent(comment)
126 self.waitUntilSettled()
127 # No approval from Jenkins so should not be enqueued
128 self.assertEqual(len(self.history), 0)
129
130 # Add an approval from Jenkins
Joshua Hesketh642824b2014-07-01 17:54:59 +1000131 A.addApproval('VRFY', 1, username='jenkins')
James E. Blair9c17dbf2014-06-23 14:21:58 -0700132 self.fake_gerrit.addEvent(comment)
133 self.waitUntilSettled()
134 self.assertEqual(len(self.history), 1)
135 self.assertEqual(self.history[0].name, job)
136
137 def test_pipeline_require_approval_email(self):
138 "Test pipeline requirement: approval email"
139 return self._test_require_approval_email('org/project1',
140 'project1-pipeline')
141
142 def test_trigger_require_approval_email(self):
143 "Test trigger requirement: approval email"
144 return self._test_require_approval_email('org/project2',
145 'project2-trigger')
146
147 def _test_require_approval_email(self, project, job):
148 self.config.set('zuul', 'layout_config',
149 'tests/fixtures/layout-requirement-email.yaml')
150 self.sched.reconfigure(self.config)
151 self.registerJobs()
152
153 A = self.fake_gerrit.addFakeChange(project, 'master', 'A')
154 # A comment event that we will keep submitting to trigger
155 comment = A.addApproval('CRVW', 2, username='nobody')
156 self.fake_gerrit.addEvent(comment)
157 self.waitUntilSettled()
158 # No approval from Jenkins so should not be enqueued
159 self.assertEqual(len(self.history), 0)
160
161 # Add an approval from Jenkins
Joshua Hesketh642824b2014-07-01 17:54:59 +1000162 A.addApproval('VRFY', 1, username='jenkins')
James E. Blair9c17dbf2014-06-23 14:21:58 -0700163 self.fake_gerrit.addEvent(comment)
164 self.waitUntilSettled()
165 self.assertEqual(len(self.history), 1)
166 self.assertEqual(self.history[0].name, job)
167
168 def test_pipeline_require_approval_vote1(self):
169 "Test pipeline requirement: approval vote with one value"
170 return self._test_require_approval_vote1('org/project1',
171 'project1-pipeline')
172
173 def test_trigger_require_approval_vote1(self):
174 "Test trigger requirement: approval vote with one value"
175 return self._test_require_approval_vote1('org/project2',
176 'project2-trigger')
177
178 def _test_require_approval_vote1(self, project, job):
179 self.config.set('zuul', 'layout_config',
180 'tests/fixtures/layout-requirement-vote1.yaml')
181 self.sched.reconfigure(self.config)
182 self.registerJobs()
183
184 A = self.fake_gerrit.addFakeChange(project, 'master', 'A')
185 # A comment event that we will keep submitting to trigger
186 comment = A.addApproval('CRVW', 2, username='nobody')
187 self.fake_gerrit.addEvent(comment)
188 self.waitUntilSettled()
189 # No approval from Jenkins so should not be enqueued
190 self.assertEqual(len(self.history), 0)
191
192 # A -1 from jenkins should not cause it to be enqueued
Joshua Hesketh642824b2014-07-01 17:54:59 +1000193 A.addApproval('VRFY', -1, username='jenkins')
James E. Blair9c17dbf2014-06-23 14:21:58 -0700194 self.fake_gerrit.addEvent(comment)
195 self.waitUntilSettled()
196 self.assertEqual(len(self.history), 0)
197
198 # A +1 should allow it to be enqueued
Joshua Hesketh642824b2014-07-01 17:54:59 +1000199 A.addApproval('VRFY', 1, username='jenkins')
James E. Blair9c17dbf2014-06-23 14:21:58 -0700200 self.fake_gerrit.addEvent(comment)
201 self.waitUntilSettled()
202 self.assertEqual(len(self.history), 1)
203 self.assertEqual(self.history[0].name, job)
204
205 def test_pipeline_require_approval_vote2(self):
206 "Test pipeline requirement: approval vote with two values"
207 return self._test_require_approval_vote2('org/project1',
208 'project1-pipeline')
209
210 def test_trigger_require_approval_vote2(self):
211 "Test trigger requirement: approval vote with two values"
212 return self._test_require_approval_vote2('org/project2',
213 'project2-trigger')
214
215 def _test_require_approval_vote2(self, project, job):
216 self.config.set('zuul', 'layout_config',
217 'tests/fixtures/layout-requirement-vote2.yaml')
218 self.sched.reconfigure(self.config)
219 self.registerJobs()
220
221 A = self.fake_gerrit.addFakeChange(project, 'master', 'A')
222 # A comment event that we will keep submitting to trigger
223 comment = A.addApproval('CRVW', 2, username='nobody')
224 self.fake_gerrit.addEvent(comment)
225 self.waitUntilSettled()
226 # No approval from Jenkins so should not be enqueued
227 self.assertEqual(len(self.history), 0)
228
229 # A -1 from jenkins should not cause it to be enqueued
Joshua Hesketh642824b2014-07-01 17:54:59 +1000230 A.addApproval('VRFY', -1, username='jenkins')
James E. Blair9c17dbf2014-06-23 14:21:58 -0700231 self.fake_gerrit.addEvent(comment)
232 self.waitUntilSettled()
233 self.assertEqual(len(self.history), 0)
234
235 # A -2 from jenkins should not cause it to be enqueued
Joshua Hesketh642824b2014-07-01 17:54:59 +1000236 A.addApproval('VRFY', -2, username='jenkins')
James E. Blair9c17dbf2014-06-23 14:21:58 -0700237 self.fake_gerrit.addEvent(comment)
238 self.waitUntilSettled()
239 self.assertEqual(len(self.history), 0)
240
Joshua Hesketh642824b2014-07-01 17:54:59 +1000241 # A +1 from jenkins should allow it to be enqueued
242 A.addApproval('VRFY', 1, username='jenkins')
James E. Blair9c17dbf2014-06-23 14:21:58 -0700243 self.fake_gerrit.addEvent(comment)
244 self.waitUntilSettled()
245 self.assertEqual(len(self.history), 1)
246 self.assertEqual(self.history[0].name, job)
247
248 # A +2 should allow it to be enqueued
249 B = self.fake_gerrit.addFakeChange(project, 'master', 'B')
250 # A comment event that we will keep submitting to trigger
251 comment = B.addApproval('CRVW', 2, username='nobody')
252 self.fake_gerrit.addEvent(comment)
253 self.waitUntilSettled()
254 self.assertEqual(len(self.history), 1)
255
Joshua Hesketh642824b2014-07-01 17:54:59 +1000256 B.addApproval('VRFY', 2, username='jenkins')
James E. Blair9c17dbf2014-06-23 14:21:58 -0700257 self.fake_gerrit.addEvent(comment)
258 self.waitUntilSettled()
259 self.assertEqual(len(self.history), 2)
260 self.assertEqual(self.history[1].name, job)
261
262 def test_pipeline_require_current_patchset(self):
263 "Test pipeline requirement: current-patchset"
264 self.config.set('zuul', 'layout_config',
265 'tests/fixtures/layout-requirement-'
266 'current-patchset.yaml')
267 self.sched.reconfigure(self.config)
268 self.registerJobs()
269 # Create two patchsets and let their tests settle out. Then
270 # comment on first patchset and check that no additional
271 # jobs are run.
272 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
273 self.fake_gerrit.addEvent(A.addApproval('CRVW', 1))
274 self.waitUntilSettled()
275 A.addPatchset()
276 self.fake_gerrit.addEvent(A.addApproval('CRVW', 1))
277 self.waitUntilSettled()
278
279 self.assertEqual(len(self.history), 2) # one job for each ps
280 self.fake_gerrit.addEvent(A.getChangeCommentEvent(1))
281 self.waitUntilSettled()
282
283 # Assert no new jobs ran after event for old patchset.
284 self.assertEqual(len(self.history), 2)
285
286 # Make sure the same event on a new PS will trigger
287 self.fake_gerrit.addEvent(A.getChangeCommentEvent(2))
288 self.waitUntilSettled()
289 self.assertEqual(len(self.history), 3)
290
291 def test_pipeline_require_open(self):
292 "Test pipeline requirement: open"
293 self.config.set('zuul', 'layout_config',
294 'tests/fixtures/layout-requirement-open.yaml')
295 self.sched.reconfigure(self.config)
296 self.registerJobs()
297
298 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
299 status='MERGED')
300 self.fake_gerrit.addEvent(A.addApproval('CRVW', 2))
301 self.waitUntilSettled()
302 self.assertEqual(len(self.history), 0)
303
304 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
305 self.fake_gerrit.addEvent(B.addApproval('CRVW', 2))
306 self.waitUntilSettled()
307 self.assertEqual(len(self.history), 1)
308
309 def test_pipeline_require_status(self):
310 "Test pipeline requirement: status"
311 self.config.set('zuul', 'layout_config',
312 'tests/fixtures/layout-requirement-status.yaml')
313 self.sched.reconfigure(self.config)
314 self.registerJobs()
315
316 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
317 status='MERGED')
318 self.fake_gerrit.addEvent(A.addApproval('CRVW', 2))
319 self.waitUntilSettled()
320 self.assertEqual(len(self.history), 0)
321
322 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
323 self.fake_gerrit.addEvent(B.addApproval('CRVW', 2))
324 self.waitUntilSettled()
325 self.assertEqual(len(self.history), 1)
Joshua Hesketh66c8e522014-06-26 15:30:08 +1000326
327 def _test_require_reject_username(self, project, job):
328 "Test negative username's match"
329 # Should only trigger if Jenkins hasn't voted.
330 self.config.set(
331 'zuul', 'layout_config',
332 'tests/fixtures/layout-requirement-reject-username.yaml')
333 self.sched.reconfigure(self.config)
334 self.registerJobs()
335
336 # add in a change with no comments
337 A = self.fake_gerrit.addFakeChange(project, 'master', 'A')
338 self.waitUntilSettled()
339 self.assertEqual(len(self.history), 0)
340
341 # add in a comment that will trigger
342 self.fake_gerrit.addEvent(A.addApproval('CRVW', 1,
343 username='reviewer'))
344 self.waitUntilSettled()
345 self.assertEqual(len(self.history), 1)
346 self.assertEqual(self.history[0].name, job)
347
348 # add in a comment from jenkins user which shouldn't trigger
349 self.fake_gerrit.addEvent(A.addApproval('VRFY', 1, username='jenkins'))
350 self.waitUntilSettled()
351 self.assertEqual(len(self.history), 1)
352
353 # Check future reviews also won't trigger as a 'jenkins' user has
354 # commented previously
355 self.fake_gerrit.addEvent(A.addApproval('CRVW', 1,
356 username='reviewer'))
357 self.waitUntilSettled()
358 self.assertEqual(len(self.history), 1)
359
360 def test_pipeline_reject_username(self):
361 "Test negative pipeline requirement: no comment from jenkins"
362 return self._test_require_reject_username('org/project1',
363 'project1-pipeline')
364
365 def test_trigger_reject_username(self):
366 "Test negative trigger requirement: no comment from jenkins"
367 return self._test_require_reject_username('org/project2',
368 'project2-trigger')
369
370 def _test_require_reject(self, project, job):
371 "Test no approval matches a reject param"
372 self.config.set(
373 'zuul', 'layout_config',
374 'tests/fixtures/layout-requirement-reject.yaml')
375 self.sched.reconfigure(self.config)
376 self.registerJobs()
377
378 A = self.fake_gerrit.addFakeChange(project, 'master', 'A')
379 self.waitUntilSettled()
380 self.assertEqual(len(self.history), 0)
381
382 # First positive vote should not queue until jenkins has +1'd
383 comment = A.addApproval('VRFY', 1, username='reviewer_a')
384 self.fake_gerrit.addEvent(comment)
385 self.waitUntilSettled()
386 self.assertEqual(len(self.history), 0)
387
388 # Jenkins should put in a +1 which will also queue
389 comment = A.addApproval('VRFY', 1, username='jenkins')
390 self.fake_gerrit.addEvent(comment)
391 self.waitUntilSettled()
392 self.assertEqual(len(self.history), 1)
393 self.assertEqual(self.history[0].name, job)
394
395 # Negative vote should not queue
396 comment = A.addApproval('VRFY', -1, username='reviewer_b')
397 self.fake_gerrit.addEvent(comment)
398 self.waitUntilSettled()
399 self.assertEqual(len(self.history), 1)
400
401 # Future approvals should do nothing
402 comment = A.addApproval('VRFY', 1, username='reviewer_c')
403 self.fake_gerrit.addEvent(comment)
404 self.waitUntilSettled()
405 self.assertEqual(len(self.history), 1)
406
407 # Change/update negative vote should queue
408 comment = A.addApproval('VRFY', 1, username='reviewer_b')
409 self.fake_gerrit.addEvent(comment)
410 self.waitUntilSettled()
411 self.assertEqual(len(self.history), 2)
412 self.assertEqual(self.history[1].name, job)
413
414 # Future approvals should also queue
415 comment = A.addApproval('VRFY', 1, username='reviewer_d')
416 self.fake_gerrit.addEvent(comment)
417 self.waitUntilSettled()
418 self.assertEqual(len(self.history), 3)
419 self.assertEqual(self.history[2].name, job)
420
421 def test_pipeline_require_reject(self):
422 "Test pipeline requirement: rejections absent"
423 return self._test_require_reject('org/project1', 'project1-pipeline')
424
425 def test_trigger_require_reject(self):
426 "Test trigger requirement: rejections absent"
427 return self._test_require_reject('org/project2', 'project2-trigger')