9c17dbf763
On further inspection, trigger requirements will still be required for parts of the kind of pipeline construction that we are using in OpenStack; the idea that they could be completely replaced by pipeline requirements is incorrect. To that end, un-deprecate trigger requirements and cleanup the testing of both of them so that each requirement is tested (relatively) independently. A small amount of requirement composition is also tested, though all possible combinations (a lot!) are not. Move this testing into a new file for organizational purposes. Also, support multiple vote values (eg, "+1" or "+2") when requiring an approval. Change-Id: I683c9a574ced0e27ced59e62b8059fef2dfd8b20
324 lines
14 KiB
Python
324 lines
14 KiB
Python
#!/usr/bin/env python
|
|
|
|
# Copyright 2012-2014 Hewlett-Packard Development Company, L.P.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
import logging
|
|
import time
|
|
|
|
from tests.base import ZuulTestCase
|
|
|
|
logging.basicConfig(level=logging.DEBUG,
|
|
format='%(asctime)s %(name)-32s '
|
|
'%(levelname)-8s %(message)s')
|
|
|
|
|
|
class TestRequirements(ZuulTestCase):
|
|
"""Test pipeline and trigger requirements"""
|
|
|
|
def test_pipeline_require_approval_newer_than(self):
|
|
"Test pipeline requirement: approval newer than"
|
|
return self._test_require_approval_newer_than('org/project1',
|
|
'project1-pipeline')
|
|
|
|
def test_trigger_require_approval_newer_than(self):
|
|
"Test trigger requirement: approval newer than"
|
|
return self._test_require_approval_newer_than('org/project2',
|
|
'project2-trigger')
|
|
|
|
def _test_require_approval_newer_than(self, project, job):
|
|
self.config.set('zuul', 'layout_config',
|
|
'tests/fixtures/layout-requirement-newer-than.yaml')
|
|
self.sched.reconfigure(self.config)
|
|
self.registerJobs()
|
|
|
|
A = self.fake_gerrit.addFakeChange(project, 'master', 'A')
|
|
# A comment event that we will keep submitting to trigger
|
|
comment = A.addApproval('CRVW', 2, username='nobody')
|
|
self.fake_gerrit.addEvent(comment)
|
|
self.waitUntilSettled()
|
|
# No +1 from Jenkins so should not be enqueued
|
|
self.assertEqual(len(self.history), 0)
|
|
|
|
# Add a too-old +1, should not be enqueued
|
|
A.addApproval('VRFY', 1, granted_on=time.time() - 72 * 60 * 60)
|
|
self.fake_gerrit.addEvent(comment)
|
|
self.waitUntilSettled()
|
|
self.assertEqual(len(self.history), 0)
|
|
|
|
# Add a recent +1
|
|
self.fake_gerrit.addEvent(A.addApproval('VRFY', 1))
|
|
self.fake_gerrit.addEvent(comment)
|
|
self.waitUntilSettled()
|
|
self.assertEqual(len(self.history), 1)
|
|
self.assertEqual(self.history[0].name, job)
|
|
|
|
def test_pipeline_require_approval_older_than(self):
|
|
"Test pipeline requirement: approval older than"
|
|
return self._test_require_approval_older_than('org/project1',
|
|
'project1-pipeline')
|
|
|
|
def test_trigger_require_approval_older_than(self):
|
|
"Test trigger requirement: approval older than"
|
|
return self._test_require_approval_older_than('org/project2',
|
|
'project2-trigger')
|
|
|
|
def _test_require_approval_older_than(self, project, job):
|
|
self.config.set('zuul', 'layout_config',
|
|
'tests/fixtures/layout-requirement-older-than.yaml')
|
|
self.sched.reconfigure(self.config)
|
|
self.registerJobs()
|
|
|
|
A = self.fake_gerrit.addFakeChange(project, 'master', 'A')
|
|
# A comment event that we will keep submitting to trigger
|
|
comment = A.addApproval('CRVW', 2, username='nobody')
|
|
self.fake_gerrit.addEvent(comment)
|
|
self.waitUntilSettled()
|
|
# No +1 from Jenkins so should not be enqueued
|
|
self.assertEqual(len(self.history), 0)
|
|
|
|
# Add a recent +1 which should not be enqueued
|
|
A.addApproval('VRFY', 1)
|
|
self.fake_gerrit.addEvent(comment)
|
|
self.waitUntilSettled()
|
|
self.assertEqual(len(self.history), 0)
|
|
|
|
# Add an old +1 which should be enqueued
|
|
A.addApproval('VRFY', 1, granted_on=time.time() - 72 * 60 * 60)
|
|
self.fake_gerrit.addEvent(comment)
|
|
self.waitUntilSettled()
|
|
self.assertEqual(len(self.history), 1)
|
|
self.assertEqual(self.history[0].name, job)
|
|
|
|
def test_pipeline_require_approval_username(self):
|
|
"Test pipeline requirement: approval username"
|
|
return self._test_require_approval_username('org/project1',
|
|
'project1-pipeline')
|
|
|
|
def test_trigger_require_approval_username(self):
|
|
"Test trigger requirement: approval username"
|
|
return self._test_require_approval_username('org/project2',
|
|
'project2-trigger')
|
|
|
|
def _test_require_approval_username(self, project, job):
|
|
self.config.set('zuul', 'layout_config',
|
|
'tests/fixtures/layout-requirement-username.yaml')
|
|
self.sched.reconfigure(self.config)
|
|
self.registerJobs()
|
|
|
|
A = self.fake_gerrit.addFakeChange(project, 'master', 'A')
|
|
# A comment event that we will keep submitting to trigger
|
|
comment = A.addApproval('CRVW', 2, username='nobody')
|
|
self.fake_gerrit.addEvent(comment)
|
|
self.waitUntilSettled()
|
|
# No approval from Jenkins so should not be enqueued
|
|
self.assertEqual(len(self.history), 0)
|
|
|
|
# Add an approval from Jenkins
|
|
A.addApproval('VRFY', 1)
|
|
self.fake_gerrit.addEvent(comment)
|
|
self.waitUntilSettled()
|
|
self.assertEqual(len(self.history), 1)
|
|
self.assertEqual(self.history[0].name, job)
|
|
|
|
def test_pipeline_require_approval_email(self):
|
|
"Test pipeline requirement: approval email"
|
|
return self._test_require_approval_email('org/project1',
|
|
'project1-pipeline')
|
|
|
|
def test_trigger_require_approval_email(self):
|
|
"Test trigger requirement: approval email"
|
|
return self._test_require_approval_email('org/project2',
|
|
'project2-trigger')
|
|
|
|
def _test_require_approval_email(self, project, job):
|
|
self.config.set('zuul', 'layout_config',
|
|
'tests/fixtures/layout-requirement-email.yaml')
|
|
self.sched.reconfigure(self.config)
|
|
self.registerJobs()
|
|
|
|
A = self.fake_gerrit.addFakeChange(project, 'master', 'A')
|
|
# A comment event that we will keep submitting to trigger
|
|
comment = A.addApproval('CRVW', 2, username='nobody')
|
|
self.fake_gerrit.addEvent(comment)
|
|
self.waitUntilSettled()
|
|
# No approval from Jenkins so should not be enqueued
|
|
self.assertEqual(len(self.history), 0)
|
|
|
|
# Add an approval from Jenkins
|
|
A.addApproval('VRFY', 1)
|
|
self.fake_gerrit.addEvent(comment)
|
|
self.waitUntilSettled()
|
|
self.assertEqual(len(self.history), 1)
|
|
self.assertEqual(self.history[0].name, job)
|
|
|
|
def test_pipeline_require_approval_vote1(self):
|
|
"Test pipeline requirement: approval vote with one value"
|
|
return self._test_require_approval_vote1('org/project1',
|
|
'project1-pipeline')
|
|
|
|
def test_trigger_require_approval_vote1(self):
|
|
"Test trigger requirement: approval vote with one value"
|
|
return self._test_require_approval_vote1('org/project2',
|
|
'project2-trigger')
|
|
|
|
def _test_require_approval_vote1(self, project, job):
|
|
self.config.set('zuul', 'layout_config',
|
|
'tests/fixtures/layout-requirement-vote1.yaml')
|
|
self.sched.reconfigure(self.config)
|
|
self.registerJobs()
|
|
|
|
A = self.fake_gerrit.addFakeChange(project, 'master', 'A')
|
|
# A comment event that we will keep submitting to trigger
|
|
comment = A.addApproval('CRVW', 2, username='nobody')
|
|
self.fake_gerrit.addEvent(comment)
|
|
self.waitUntilSettled()
|
|
# No approval from Jenkins so should not be enqueued
|
|
self.assertEqual(len(self.history), 0)
|
|
|
|
# A -1 from jenkins should not cause it to be enqueued
|
|
A.addApproval('VRFY', -1)
|
|
self.fake_gerrit.addEvent(comment)
|
|
self.waitUntilSettled()
|
|
self.assertEqual(len(self.history), 0)
|
|
|
|
# A +1 should allow it to be enqueued
|
|
A.addApproval('VRFY', 1)
|
|
self.fake_gerrit.addEvent(comment)
|
|
self.waitUntilSettled()
|
|
self.assertEqual(len(self.history), 1)
|
|
self.assertEqual(self.history[0].name, job)
|
|
|
|
def test_pipeline_require_approval_vote2(self):
|
|
"Test pipeline requirement: approval vote with two values"
|
|
return self._test_require_approval_vote2('org/project1',
|
|
'project1-pipeline')
|
|
|
|
def test_trigger_require_approval_vote2(self):
|
|
"Test trigger requirement: approval vote with two values"
|
|
return self._test_require_approval_vote2('org/project2',
|
|
'project2-trigger')
|
|
|
|
def _test_require_approval_vote2(self, project, job):
|
|
self.config.set('zuul', 'layout_config',
|
|
'tests/fixtures/layout-requirement-vote2.yaml')
|
|
self.sched.reconfigure(self.config)
|
|
self.registerJobs()
|
|
|
|
A = self.fake_gerrit.addFakeChange(project, 'master', 'A')
|
|
# A comment event that we will keep submitting to trigger
|
|
comment = A.addApproval('CRVW', 2, username='nobody')
|
|
self.fake_gerrit.addEvent(comment)
|
|
self.waitUntilSettled()
|
|
# No approval from Jenkins so should not be enqueued
|
|
self.assertEqual(len(self.history), 0)
|
|
|
|
# A -1 from jenkins should not cause it to be enqueued
|
|
A.addApproval('VRFY', -1)
|
|
self.fake_gerrit.addEvent(comment)
|
|
self.waitUntilSettled()
|
|
self.assertEqual(len(self.history), 0)
|
|
|
|
# A -2 from jenkins should not cause it to be enqueued
|
|
A.addApproval('VRFY', -2)
|
|
self.fake_gerrit.addEvent(comment)
|
|
self.waitUntilSettled()
|
|
self.assertEqual(len(self.history), 0)
|
|
|
|
# A +1 should allow it to be enqueued
|
|
A.addApproval('VRFY', 1)
|
|
self.fake_gerrit.addEvent(comment)
|
|
self.waitUntilSettled()
|
|
self.assertEqual(len(self.history), 1)
|
|
self.assertEqual(self.history[0].name, job)
|
|
|
|
# A +2 should allow it to be enqueued
|
|
B = self.fake_gerrit.addFakeChange(project, 'master', 'B')
|
|
# A comment event that we will keep submitting to trigger
|
|
comment = B.addApproval('CRVW', 2, username='nobody')
|
|
self.fake_gerrit.addEvent(comment)
|
|
self.waitUntilSettled()
|
|
self.assertEqual(len(self.history), 1)
|
|
|
|
B.addApproval('VRFY', 2)
|
|
self.fake_gerrit.addEvent(comment)
|
|
self.waitUntilSettled()
|
|
self.assertEqual(len(self.history), 2)
|
|
self.assertEqual(self.history[1].name, job)
|
|
|
|
def test_pipeline_require_current_patchset(self):
|
|
"Test pipeline requirement: current-patchset"
|
|
self.config.set('zuul', 'layout_config',
|
|
'tests/fixtures/layout-requirement-'
|
|
'current-patchset.yaml')
|
|
self.sched.reconfigure(self.config)
|
|
self.registerJobs()
|
|
# Create two patchsets and let their tests settle out. Then
|
|
# comment on first patchset and check that no additional
|
|
# jobs are run.
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
|
|
self.fake_gerrit.addEvent(A.addApproval('CRVW', 1))
|
|
self.waitUntilSettled()
|
|
A.addPatchset()
|
|
self.fake_gerrit.addEvent(A.addApproval('CRVW', 1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(len(self.history), 2) # one job for each ps
|
|
self.fake_gerrit.addEvent(A.getChangeCommentEvent(1))
|
|
self.waitUntilSettled()
|
|
|
|
# Assert no new jobs ran after event for old patchset.
|
|
self.assertEqual(len(self.history), 2)
|
|
|
|
# Make sure the same event on a new PS will trigger
|
|
self.fake_gerrit.addEvent(A.getChangeCommentEvent(2))
|
|
self.waitUntilSettled()
|
|
self.assertEqual(len(self.history), 3)
|
|
|
|
def test_pipeline_require_open(self):
|
|
"Test pipeline requirement: open"
|
|
self.config.set('zuul', 'layout_config',
|
|
'tests/fixtures/layout-requirement-open.yaml')
|
|
self.sched.reconfigure(self.config)
|
|
self.registerJobs()
|
|
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
status='MERGED')
|
|
self.fake_gerrit.addEvent(A.addApproval('CRVW', 2))
|
|
self.waitUntilSettled()
|
|
self.assertEqual(len(self.history), 0)
|
|
|
|
B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
|
|
self.fake_gerrit.addEvent(B.addApproval('CRVW', 2))
|
|
self.waitUntilSettled()
|
|
self.assertEqual(len(self.history), 1)
|
|
|
|
def test_pipeline_require_status(self):
|
|
"Test pipeline requirement: status"
|
|
self.config.set('zuul', 'layout_config',
|
|
'tests/fixtures/layout-requirement-status.yaml')
|
|
self.sched.reconfigure(self.config)
|
|
self.registerJobs()
|
|
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
status='MERGED')
|
|
self.fake_gerrit.addEvent(A.addApproval('CRVW', 2))
|
|
self.waitUntilSettled()
|
|
self.assertEqual(len(self.history), 0)
|
|
|
|
B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
|
|
self.fake_gerrit.addEvent(B.addApproval('CRVW', 2))
|
|
self.waitUntilSettled()
|
|
self.assertEqual(len(self.history), 1)
|