zuul/tests/test_requirements.py
James E. Blair 9c17dbf763 Cleanup approval requirement testing
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
2014-06-24 09:38:31 -07:00

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)