github.com/munnerz/test-infra@v0.0.0-20190108210205-ce3d181dc989/gubernator/github/periodic_sync_test.py (about) 1 #!/usr/bin/env python 2 3 # Copyright 2018 The Kubernetes Authors. 4 # 5 # Licensed under the Apache License, Version 2.0 (the "License"); 6 # you may not use this file except in compliance with the License. 7 # You may obtain 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, 13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 # See the License for the specific language governing permissions and 15 # limitations under the License. 16 17 # pylint: disable=no-self-use 18 19 import cPickle as pickle 20 import json 21 22 import webtest 23 24 from google.appengine.ext import deferred 25 from google.appengine.ext import testbed 26 27 import main_test 28 import models 29 import periodic_sync 30 import secrets 31 32 app = webtest.TestApp(periodic_sync.app) 33 34 TOKEN = 'gh_auth_secret' 35 36 def pr_data(number): 37 return { 38 'number': number, 39 'state': 'open', 40 'user': {'login': 'a'}, 41 'assignees': [{'login': 'b'}], 42 'title': 'some fix %d' % number, 43 'head': {'sha': 'abcdef'}, 44 } 45 46 class SyncTest(main_test.TestBase): 47 def setUp(self): 48 self.init_stubs() 49 self.taskqueue = self.testbed.get_stub(testbed.TASKQUEUE_SERVICE_NAME) 50 secrets.put('github_token', TOKEN, per_host=False) 51 self.gh_data = {} 52 53 def inject_pr(self, repo, number): 54 models.GHIssueDigest.make( 55 repo, number, True, True, [], 56 {'author': 'someone', 'assignees': [], 'title': '#%d' % number}, 57 None).put() 58 59 def get_deferred_funcs(self): 60 out = [] 61 for task in self.taskqueue.get_filtered_tasks(): 62 func, args, _kwargs = pickle.loads(task.payload) 63 out.append((func.__name__, args)) 64 return out 65 66 def test_repo_dispatch(self): 67 self.inject_pr('a/b', 3) 68 self.inject_pr('a/b', 4) 69 self.inject_pr('k/t', 90) 70 71 app.get('/sync') 72 73 self.assertEqual(self.get_deferred_funcs(), 74 [('sync_repo', (TOKEN, 'a/b')), 75 ('sync_repo', (TOKEN, 'k/t'))]) 76 77 def urlfetch_github_stub(self, url, _payload, method, 78 headers, _request, response, **_kwargs): 79 assert method == 'GET' 80 assert headers[0].key() == 'Authorization' 81 assert headers[0].value() == 'token ' + TOKEN 82 path = url[url.find('.com')+4:] 83 content, response_headers = self.gh_data[path] 84 response.set_content(json.dumps(content)) 85 response.set_statuscode(200) 86 for k, v in response_headers.iteritems(): 87 header = response.add_header() 88 header.set_key(k) 89 header.set_value(v) 90 91 def init_github_fake(self): 92 # Theoretically, I should be able to pass this to init_urlfetch_stub. 93 # Practically, that doesn't work for unknown reasons, and this is fine. 94 uf = self.testbed.get_stub('urlfetch') 95 uf._urlmatchers_to_fetch_functions.append( # pylint: disable=protected-access 96 (lambda u: u.startswith('https://api.github.com'), self.urlfetch_github_stub)) 97 98 def test_get_prs_from_github(self): 99 self.init_github_fake() 100 101 base_url = '/repos/a/b/pulls?state=open&per_page=100' 102 def make_headers(page): 103 frag = '<https://api.github.com%s' % base_url 104 link = '%s&page=4>; rel="last"' % frag 105 if page < 4: 106 link = '%s&page=%d>; rel="next", %s' % (frag, page + 1, link) 107 if page > 1: 108 link = '%s&page=%d>; rel="prev", %s' % (frag, page - 1, link) 109 print link 110 return {'Link': link} 111 112 prs = [pr_data(n) for n in range(400)] 113 self.gh_data = { 114 base_url: (prs[:100], make_headers(1)), 115 base_url + '&page=2': (prs[100:200], make_headers(2)), 116 base_url + '&page=3': (prs[200:300], make_headers(3)), 117 base_url + '&page=4': (prs[300:], make_headers(4)), 118 } 119 120 got_prs = periodic_sync.get_prs_from_github(TOKEN, 'a/b') 121 got_pr_nos = [pr['number'] for pr in got_prs] 122 expected_pr_nos = [pr['number'] for pr in prs] 123 124 self.assertEqual(got_pr_nos, expected_pr_nos) 125 126 def test_sync_repo(self): 127 self.init_github_fake() 128 self.gh_data = { 129 '/repos/a/b/pulls?state=open&per_page=100': 130 ([pr_data(11), pr_data(12), pr_data(13)], {}), 131 } 132 133 # PRs <10 are closed 134 # PRs >10 are open 135 self.inject_pr('a/b', 1) 136 self.inject_pr('a/b', 2) 137 self.inject_pr('a/b', 3) 138 self.inject_pr('a/b', 11) 139 self.inject_pr('a/b', 12) 140 141 periodic_sync.sync_repo(TOKEN, 'a/b') 142 143 for task in self.taskqueue.get_filtered_tasks(): 144 deferred.run(task.payload) 145 146 open_prs = models.GHIssueDigest.find_open_prs().fetch() 147 open_prs = [pr.number for pr in open_prs] 148 149 self.assertEqual(open_prs, [11, 12, 13])