Refactor branch protection test infrastructure

Branch protection rules are not just about required status so refactor
it in the test framework so we can extend them in the future.

Change-Id: I1e32ebb57b27bce898b074e419299a1803853608
changes/34/709834/1
Tobias Henkel 2020-02-25 15:11:39 +01:00
parent 32bfbae465
commit df2e3af642
No known key found for this signature in database
GPG Key ID: 03750DEC158E5FA2
2 changed files with 41 additions and 22 deletions

View File

@ -13,6 +13,7 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from collections import defaultdict
import github3.exceptions
import re
@ -33,9 +34,13 @@ class FakeUser(object):
class FakeBranch(object):
def __init__(self, branch='master', protected=False):
def __init__(self, fake_repo, branch='master', protected=False):
self.name = branch
self.protected = protected
self._fake_repo = fake_repo
@property
def protected(self):
return self.name in self._fake_repo._branch_protection_rules
def as_dict(self):
return {
@ -173,7 +178,7 @@ class FakeCommit(object):
class FakeRepository(object):
def __init__(self, name, data):
self._api = FAKE_BASE_URL
self._branches = [FakeBranch()]
self._branches = [FakeBranch(self)]
self._commits = {}
self.data = data
self.name = name
@ -187,6 +192,9 @@ class FakeRepository(object):
# would do in case the permission is not sufficient or missing at all.
self._permissions = {}
# List of branch protection rules
self._branch_protection_rules = defaultdict(FakeBranchProtectionRule)
# fail the next commit requests with 404
self.fail_not_found = 0
@ -196,11 +204,15 @@ class FakeRepository(object):
return [b for b in self._branches if b.protected]
return self._branches
def _set_branch_protection(self, branch_name, protected):
for branch in self._branches:
if branch.name == branch_name:
branch.protected = protected
return
def _set_branch_protection(self, branch_name, protected=True,
contexts=None):
if not protected and branch_name in self._branch_protection_rules:
del self._branch_protection_rules[branch_name]
return
rule = self._branch_protection_rules[branch_name]
rule.pattern = branch_name
rule.required_contexts = contexts or []
def _set_permission(self, key, value):
# NOTE (felix): Currently, this is only used to mock a repo with
@ -220,7 +232,7 @@ class FakeRepository(object):
return client.session.get(url, headers)
def _create_branch(self, branch):
self._branches.append((FakeBranch(branch=branch)))
self._branches.append((FakeBranch(self, branch=branch)))
def _delete_branch(self, branch_name):
self._branches = [b for b in self._branches if b.name != branch_name]
@ -375,14 +387,15 @@ class FakeRepository(object):
return None
def get_url_protection(self, branch):
contexts = self.data.required_contexts.get((self.name, branch), [])
if not contexts:
rule = self._branch_protection_rules.get(branch)
if not rule:
# Note that GitHub returns 404 if branch protection is off so do
# the same here as well
return FakeResponse({}, 404)
data = {
'required_status_checks': {
'contexts': contexts
'contexts': rule.required_contexts
}
}
return FakeResponse(data)
@ -551,11 +564,17 @@ class FakeGithubSession(object):
return repo.get_url(request, params=params)
class FakeBranchProtectionRule:
def __init__(self):
self.pattern = None
self.required_contexts = []
class FakeGithubData(object):
def __init__(self, pull_requests):
self.pull_requests = pull_requests
self.repos = {}
self.required_contexts = {}
class FakeGithubClient(object):

View File

@ -982,9 +982,9 @@ class TestGithubDriver(ZuulTestCase):
@simple_layout('layouts/gate-github.yaml', driver='github')
def test_status_checks(self):
github = self.fake_github.getGithubClient()
github._data.required_contexts[('org/project', 'master')] = [
'tenant-one/check',
'tenant-one/gate']
repo = github.repo_from_project('org/project')
repo._set_branch_protection(
'master', contexts=['tenant-one/check', 'tenant-one/gate'])
A = self.fake_github.openFakePullRequest('org/project', 'master', 'A')
self.fake_github.emitEvent(A.getPullRequestOpenedEvent())
@ -1153,9 +1153,9 @@ class TestGithubDriver(ZuulTestCase):
merge fails because cherry-pick is not supported by github.
"""
github = self.fake_github.getGithubClient()
github._data.required_contexts[('org/project', 'master')] = [
'tenant-one/check',
'tenant-one/gate']
repo = github.repo_from_project('org/project')
repo._set_branch_protection(
'master', contexts=['tenant-one/check', 'tenant-one/gate'])
A = self.fake_github.openFakePullRequest('org/project', 'master', 'A')
self.fake_github.emitEvent(A.getPullRequestOpenedEvent())
@ -1182,9 +1182,9 @@ class TestGithubDriver(ZuulTestCase):
merge fails because cherry-pick is not supported by github.
"""
github = self.fake_github.getGithubClient()
github._data.required_contexts[('org/project', 'master')] = [
'tenant-one/check',
'tenant-one/gate']
repo = github.repo_from_project('org/project')
repo._set_branch_protection(
'master', contexts=['tenant-one/check', 'tenant-one/gate'])
A = self.fake_github.openFakePullRequest('org/project', 'master', 'A')
self.fake_github.emitEvent(A.getPullRequestOpenedEvent())