| #!/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 time |
| |
| from tests.base import ZuulTestCase |
| |
| |
| class TestRequirementsApprovalNewerThan(ZuulTestCase): |
| """Requirements with a newer-than comment requirement""" |
| |
| tenant_config_file = 'config/requirements/newer-than/main.yaml' |
| |
| def test_pipeline_require_approval_newer_than(self): |
| "Test pipeline requirement: approval newer than" |
| return self._test_require_approval_newer_than('org/project1', |
| 'project1-job') |
| |
| def test_trigger_require_approval_newer_than(self): |
| "Test trigger requirement: approval newer than" |
| return self._test_require_approval_newer_than('org/project2', |
| 'project2-job') |
| |
| def _test_require_approval_newer_than(self, project, job): |
| A = self.fake_gerrit.addFakeChange(project, 'master', 'A') |
| # A comment event that we will keep submitting to trigger |
| comment = A.addApproval('code-review', 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('verified', 1, username='jenkins', |
| 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('verified', 1, |
| username='jenkins')) |
| self.fake_gerrit.addEvent(comment) |
| self.waitUntilSettled() |
| self.assertEqual(len(self.history), 1) |
| self.assertEqual(self.history[0].name, job) |
| |
| |
| class TestRequirementsApprovalOlderThan(ZuulTestCase): |
| """Requirements with a older-than comment requirement""" |
| |
| tenant_config_file = 'config/requirements/older-than/main.yaml' |
| |
| def test_pipeline_require_approval_older_than(self): |
| "Test pipeline requirement: approval older than" |
| return self._test_require_approval_older_than('org/project1', |
| 'project1-job') |
| |
| def test_trigger_require_approval_older_than(self): |
| "Test trigger requirement: approval older than" |
| return self._test_require_approval_older_than('org/project2', |
| 'project2-job') |
| |
| def _test_require_approval_older_than(self, project, job): |
| A = self.fake_gerrit.addFakeChange(project, 'master', 'A') |
| # A comment event that we will keep submitting to trigger |
| comment = A.addApproval('code-review', 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('verified', 1) |
| self.fake_gerrit.addEvent(comment) |
| self.waitUntilSettled() |
| self.assertEqual(len(self.history), 0) |
| |
| # Add an old +1 which should be enqueued |
| A.addApproval('verified', 1, username='jenkins', |
| 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) |
| |
| |
| class TestRequirementsUserName(ZuulTestCase): |
| """Requirements with a username requirement""" |
| |
| tenant_config_file = 'config/requirements/username/main.yaml' |
| |
| def test_pipeline_require_approval_username(self): |
| "Test pipeline requirement: approval username" |
| return self._test_require_approval_username('org/project1', |
| 'project1-job') |
| |
| def test_trigger_require_approval_username(self): |
| "Test trigger requirement: approval username" |
| return self._test_require_approval_username('org/project2', |
| 'project2-job') |
| |
| def _test_require_approval_username(self, project, job): |
| A = self.fake_gerrit.addFakeChange(project, 'master', 'A') |
| # A comment event that we will keep submitting to trigger |
| comment = A.addApproval('code-review', 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('verified', 1, username='jenkins') |
| self.fake_gerrit.addEvent(comment) |
| self.waitUntilSettled() |
| self.assertEqual(len(self.history), 1) |
| self.assertEqual(self.history[0].name, job) |
| |
| |
| class TestRequirementsEmail(ZuulTestCase): |
| """Requirements with a email requirement""" |
| |
| tenant_config_file = 'config/requirements/email/main.yaml' |
| |
| def test_pipeline_require_approval_email(self): |
| "Test pipeline requirement: approval email" |
| return self._test_require_approval_email('org/project1', |
| 'project1-job') |
| |
| def test_trigger_require_approval_email(self): |
| "Test trigger requirement: approval email" |
| return self._test_require_approval_email('org/project2', |
| 'project2-job') |
| |
| def _test_require_approval_email(self, project, job): |
| A = self.fake_gerrit.addFakeChange(project, 'master', 'A') |
| # A comment event that we will keep submitting to trigger |
| comment = A.addApproval('code-review', 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('verified', 1, username='jenkins') |
| self.fake_gerrit.addEvent(comment) |
| self.waitUntilSettled() |
| self.assertEqual(len(self.history), 1) |
| self.assertEqual(self.history[0].name, job) |
| |
| |
| class TestRequirementsVote1(ZuulTestCase): |
| """Requirements with a voting requirement""" |
| |
| tenant_config_file = 'config/requirements/vote1/main.yaml' |
| |
| def test_pipeline_require_approval_vote1(self): |
| "Test pipeline requirement: approval vote with one value" |
| return self._test_require_approval_vote1('org/project1', |
| 'project1-job') |
| |
| def test_trigger_require_approval_vote1(self): |
| "Test trigger requirement: approval vote with one value" |
| return self._test_require_approval_vote1('org/project2', |
| 'project2-job') |
| |
| def _test_require_approval_vote1(self, project, job): |
| A = self.fake_gerrit.addFakeChange(project, 'master', 'A') |
| # A comment event that we will keep submitting to trigger |
| comment = A.addApproval('code-review', 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('verified', -1, username='jenkins') |
| self.fake_gerrit.addEvent(comment) |
| self.waitUntilSettled() |
| self.assertEqual(len(self.history), 0) |
| |
| # A +1 should allow it to be enqueued |
| A.addApproval('verified', 1, username='jenkins') |
| self.fake_gerrit.addEvent(comment) |
| self.waitUntilSettled() |
| self.assertEqual(len(self.history), 1) |
| self.assertEqual(self.history[0].name, job) |
| |
| |
| class TestRequirementsVote2(ZuulTestCase): |
| """Requirements with a voting requirement""" |
| |
| tenant_config_file = 'config/requirements/vote2/main.yaml' |
| |
| def test_pipeline_require_approval_vote2(self): |
| "Test pipeline requirement: approval vote with two values" |
| return self._test_require_approval_vote2('org/project1', |
| 'project1-job') |
| |
| def test_trigger_require_approval_vote2(self): |
| "Test trigger requirement: approval vote with two values" |
| return self._test_require_approval_vote2('org/project2', |
| 'project2-job') |
| |
| def _test_require_approval_vote2(self, project, job): |
| A = self.fake_gerrit.addFakeChange(project, 'master', 'A') |
| # A comment event that we will keep submitting to trigger |
| comment = A.addApproval('code-review', 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('verified', -1, username='jenkins') |
| 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('verified', -2, username='jenkins') |
| self.fake_gerrit.addEvent(comment) |
| self.waitUntilSettled() |
| self.assertEqual(len(self.history), 0) |
| |
| # A +1 from jenkins should allow it to be enqueued |
| A.addApproval('verified', 1, username='jenkins') |
| self.fake_gerrit.addEvent(comment) |
| self.waitUntilSettled() |
| self.assertEqual(len(self.history), 1) |
| self.assertEqual(self.history[0].name, job) |
| |
| # A +2 from nobody should not cause 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('code-review', 2, username='nobody') |
| self.fake_gerrit.addEvent(comment) |
| self.waitUntilSettled() |
| self.assertEqual(len(self.history), 1) |
| |
| # A +2 from jenkins should allow it to be enqueued |
| B.addApproval('verified', 2, username='jenkins') |
| self.fake_gerrit.addEvent(comment) |
| self.waitUntilSettled() |
| self.assertEqual(len(self.history), 2) |
| self.assertEqual(self.history[1].name, job) |
| |
| |
| class TestRequirementsState(ZuulTestCase): |
| """Requirements with simple state requirement""" |
| |
| tenant_config_file = 'config/requirements/state/main.yaml' |
| |
| def test_pipeline_require_current_patchset(self): |
| # 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('current-project', 'master', 'A') |
| self.fake_gerrit.addEvent(A.addApproval('code-review', 1)) |
| self.waitUntilSettled() |
| A.addPatchset() |
| self.fake_gerrit.addEvent(A.addApproval('code-review', 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): |
| A = self.fake_gerrit.addFakeChange('open-project', 'master', 'A', |
| status='MERGED') |
| self.fake_gerrit.addEvent(A.addApproval('code-review', 2)) |
| self.waitUntilSettled() |
| self.assertEqual(len(self.history), 0) |
| |
| B = self.fake_gerrit.addFakeChange('open-project', 'master', 'B') |
| self.fake_gerrit.addEvent(B.addApproval('code-review', 2)) |
| self.waitUntilSettled() |
| self.assertEqual(len(self.history), 1) |
| |
| def test_pipeline_require_status(self): |
| A = self.fake_gerrit.addFakeChange('status-project', 'master', 'A', |
| status='MERGED') |
| self.fake_gerrit.addEvent(A.addApproval('code-review', 2)) |
| self.waitUntilSettled() |
| self.assertEqual(len(self.history), 0) |
| |
| B = self.fake_gerrit.addFakeChange('status-project', 'master', 'B') |
| self.fake_gerrit.addEvent(B.addApproval('code-review', 2)) |
| self.waitUntilSettled() |
| self.assertEqual(len(self.history), 1) |
| |
| |
| class TestRequirementsRejectUsername(ZuulTestCase): |
| """Requirements with reject username requirement""" |
| |
| tenant_config_file = 'config/requirements/reject-username/main.yaml' |
| |
| def _test_require_reject_username(self, project, job): |
| "Test negative username's match" |
| # Should only trigger if Jenkins hasn't voted. |
| # add in a change with no comments |
| A = self.fake_gerrit.addFakeChange(project, 'master', 'A') |
| self.waitUntilSettled() |
| self.assertEqual(len(self.history), 0) |
| |
| # add in a comment that will trigger |
| self.fake_gerrit.addEvent(A.addApproval('code-review', 1, |
| username='reviewer')) |
| self.waitUntilSettled() |
| self.assertEqual(len(self.history), 1) |
| self.assertEqual(self.history[0].name, job) |
| |
| # add in a comment from jenkins user which shouldn't trigger |
| self.fake_gerrit.addEvent(A.addApproval('verified', 1, |
| username='jenkins')) |
| self.waitUntilSettled() |
| self.assertEqual(len(self.history), 1) |
| |
| # Check future reviews also won't trigger as a 'jenkins' user has |
| # commented previously |
| self.fake_gerrit.addEvent(A.addApproval('code-review', 1, |
| username='reviewer')) |
| self.waitUntilSettled() |
| self.assertEqual(len(self.history), 1) |
| |
| def test_pipeline_reject_username(self): |
| "Test negative pipeline requirement: no comment from jenkins" |
| return self._test_require_reject_username('org/project1', |
| 'project1-job') |
| |
| def test_trigger_reject_username(self): |
| "Test negative trigger requirement: no comment from jenkins" |
| return self._test_require_reject_username('org/project2', |
| 'project2-job') |
| |
| |
| class TestRequirementsReject(ZuulTestCase): |
| """Requirements with reject requirement""" |
| |
| tenant_config_file = 'config/requirements/reject/main.yaml' |
| |
| def _test_require_reject(self, project, job): |
| "Test no approval matches a reject param" |
| A = self.fake_gerrit.addFakeChange(project, 'master', 'A') |
| self.waitUntilSettled() |
| self.assertEqual(len(self.history), 0) |
| |
| # First positive vote should not queue until jenkins has +1'd |
| comment = A.addApproval('verified', 1, username='reviewer_a') |
| self.fake_gerrit.addEvent(comment) |
| self.waitUntilSettled() |
| self.assertEqual(len(self.history), 0) |
| |
| # Jenkins should put in a +1 which will also queue |
| comment = A.addApproval('verified', 1, username='jenkins') |
| self.fake_gerrit.addEvent(comment) |
| self.waitUntilSettled() |
| self.assertEqual(len(self.history), 1) |
| self.assertEqual(self.history[0].name, job) |
| |
| # Negative vote should not queue |
| comment = A.addApproval('verified', -1, username='reviewer_b') |
| self.fake_gerrit.addEvent(comment) |
| self.waitUntilSettled() |
| self.assertEqual(len(self.history), 1) |
| |
| # Future approvals should do nothing |
| comment = A.addApproval('verified', 1, username='reviewer_c') |
| self.fake_gerrit.addEvent(comment) |
| self.waitUntilSettled() |
| self.assertEqual(len(self.history), 1) |
| |
| # Change/update negative vote should queue |
| comment = A.addApproval('verified', 1, username='reviewer_b') |
| self.fake_gerrit.addEvent(comment) |
| self.waitUntilSettled() |
| self.assertEqual(len(self.history), 2) |
| self.assertEqual(self.history[1].name, job) |
| |
| # Future approvals should also queue |
| comment = A.addApproval('verified', 1, username='reviewer_d') |
| self.fake_gerrit.addEvent(comment) |
| self.waitUntilSettled() |
| self.assertEqual(len(self.history), 3) |
| self.assertEqual(self.history[2].name, job) |
| |
| def test_pipeline_require_reject(self): |
| "Test pipeline requirement: rejections absent" |
| return self._test_require_reject('org/project1', 'project1-job') |
| |
| def test_trigger_require_reject(self): |
| "Test trigger requirement: rejections absent" |
| return self._test_require_reject('org/project2', 'project2-job') |