blob: 52e3973243dde2f7be1e53091de222487e9a0bee [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 Heskethb2068e82014-06-26 15:30:08 +1000326
327 def test_pipeline_require_negative_username(self):
328 "Test negative pipeline requirement: no comment from jenkins"
329 return self._test_require_negative_username('org/project1',
330 'project1-pipeline')
331
332 def test_trigger_require_negative_username(self):
333 "Test negative trigger requirement: no comment from jenkins"
334 return self._test_require_negative_username('org/project2',
335 'project2-trigger')
336
337 def _test_require_negative_username(self, project, job):
338 "Test negative username's match"
339 # Should only trigger if Jenkins hasn't voted.
340 self.config.set(
341 'zuul', 'layout_config',
342 'tests/fixtures/layout-requirement-negative-username.yaml')
343 self.sched.reconfigure(self.config)
344 self.registerJobs()
345
346 # add in a change with no comments
347 A = self.fake_gerrit.addFakeChange(project, 'master', 'A')
348 self.waitUntilSettled()
349 self.assertEqual(len(self.history), 0)
350
351 # add in a comment that will trigger
352 self.fake_gerrit.addEvent(A.addApproval('CRVW', 1,
353 username='reviewer'))
354 self.waitUntilSettled()
355 self.assertEqual(len(self.history), 1)
356 self.assertEqual(self.history[0].name, job)
357
358 # add in a comment from jenkins user which shouldn't trigger
359 self.fake_gerrit.addEvent(A.addApproval('VRFY', 1, username='jenkins'))
360 self.waitUntilSettled()
361 self.assertEqual(len(self.history), 1)
362
363 # Check future reviews also won't trigger as a 'jenkins' user has
364 # commented previously
365 self.fake_gerrit.addEvent(A.addApproval('CRVW', 1,
366 username='reviewer'))
367 self.waitUntilSettled()
368 self.assertEqual(len(self.history), 1)
369
370 def test_pipeline_require_any(self):
371 "Test pipeline requirement: any requirement passes"
372 return self._test_require_any('org/project1', 'project1-pipeline')
373
374 def test_trigger_require_any(self):
375 "Test trigger requirement: any requirement passes"
376 return self._test_require_any('org/project2', 'project2-trigger')
377
378 def _test_require_any(self, project, job):
379 "Test any of the given requirements are matched"
380 self.config.set(
381 'zuul', 'layout_config',
382 'tests/fixtures/layout-requirement-any.yaml')
383 self.sched.reconfigure(self.config)
384 self.registerJobs()
385
386 A = self.fake_gerrit.addFakeChange(project, 'master', 'A')
387 # A comment event that we will keep submitting to trigger
388 comment = A.addApproval('CRVW', 1, username='nobody')
389 self.fake_gerrit.addEvent(comment)
390 self.waitUntilSettled()
391 # No approval from Jenkins so should not be enqueued
392 self.assertEqual(len(self.history), 0)
393
394 # A +1 from jenkins should allow it to be enqueued
395 A.addApproval('VRFY', 1, username='jenkins')
396 self.fake_gerrit.addEvent(comment)
397 self.waitUntilSettled()
398 self.assertEqual(len(self.history), 1)
399 self.assertEqual(self.history[0].name, job)
400
401 # A non-negative from a non-core should not queue
402 B = self.fake_gerrit.addFakeChange(project, 'master', 'B')
403 # A comment event that we will keep submitting to trigger
404 comment = B.addApproval('CRVW', 1, username='nobody')
405 self.fake_gerrit.addEvent(comment)
406 self.waitUntilSettled()
407 self.assertEqual(len(self.history), 1)
408
409 # A non-negative from a core member should queue
410 B.addApproval('CRVW', 2, username='core-reviewer')
411 self.fake_gerrit.addEvent(comment)
412 self.waitUntilSettled()
413 self.assertEqual(len(self.history), 2)
414 self.assertEqual(self.history[1].name, job)
415
416 def test_pipeline_require_all(self):
417 "Test pipeline requirement: all requirements pass"
418 return self._test_require_all('org/project1', 'project1-pipeline')
419
420 def test_trigger_require_all(self):
421 "Test trigger requirement: all requirements pass"
422 return self._test_require_all('org/project2', 'project2-trigger')
423
424 def _test_require_all(self, project, job):
425 "Test all of the given requirements are matched"
426 self.config.set(
427 'zuul', 'layout_config',
428 'tests/fixtures/layout-requirement-all.yaml')
429 self.sched.reconfigure(self.config)
430 self.registerJobs()
431
432 A = self.fake_gerrit.addFakeChange(project, 'master', 'A')
433 self.waitUntilSettled()
434 self.assertEqual(len(self.history), 0)
435
436 # A +2 from 'nobody' only satisfies the non-negative requirement,
437 # not the requirement to be from 'jenkins'
438 comment = A.addApproval('VRFY', 1, username='nobody')
439 self.fake_gerrit.addEvent(comment)
440 self.waitUntilSettled()
441 self.assertEqual(len(self.history), 0)
442
443 B = self.fake_gerrit.addFakeChange(project, 'master', 'A')
444 self.waitUntilSettled()
445 self.assertEqual(len(self.history), 0)
446
447 # A +2 from Jenkins satisfies both the user condition and the
448 # non-negative condition
449 comment = B.addApproval('VRFY', 2, username='jenkins')
450 self.fake_gerrit.addEvent(comment)
451 self.waitUntilSettled()
452 self.assertEqual(len(self.history), 1)
453 self.assertEqual(self.history[0].name, job)