github.com/abayer/test-infra@v0.0.5/gubernator/view_pr_test.py (about) 1 #!/usr/bin/env python 2 3 # Copyright 2016 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 import datetime 18 import unittest 19 20 # TODO(fejta): use non-relative imports 21 # https://google.github.io/styleguide/pyguide.html?showone=Packages#Packages 22 import gcs_async_test 23 from github import models 24 import main_test 25 import view_pr 26 27 from webapp2_extras import securecookie 28 29 30 app = main_test.app 31 write = gcs_async_test.write 32 33 class PathTest(unittest.TestCase): 34 def test_org_repo(self): 35 def check(path, org, repo): 36 actual_org, actual_repo = view_pr.org_repo(path, 'kubernetes', 'kubernetes') 37 self.assertEquals(actual_org, org) 38 self.assertEquals(actual_repo, repo) 39 40 check('', 'kubernetes', 'kubernetes') 41 check('/test-infra', 'kubernetes', 'test-infra') 42 check('/kubernetes', 'kubernetes', 'kubernetes') 43 check('/kubernetes/test-infra', 'kubernetes', 'test-infra') 44 check('/kubernetes/kubernetes', 'kubernetes', 'kubernetes') 45 check('/google/cadvisor', 'google', 'cadvisor') 46 47 def test_pr_path(self): 48 def check(org, repo, pr, path): 49 actual_path = view_pr.pr_path(org, repo, pr, 'kubernetes', 'kubernetes', 'pull_prefix') 50 self.assertEquals(actual_path, '%s/%s' % ('pull_prefix', path)) 51 52 check('kubernetes', 'kubernetes', 1234, 1234) 53 check('kubernetes', 'kubernetes', 'batch', 'batch') 54 check('kubernetes', 'test-infra', 555, 'test-infra/555') 55 check('kubernetes', 'test-infra', 'batch', 'test-infra/batch') 56 check('google', 'cadvisor', '555', 'google_cadvisor/555') 57 check('google', 'cadvisor', 'batch', 'google_cadvisor/batch') 58 59 60 class PRTest(main_test.TestBase): 61 BUILDS = { 62 'build': [('12', {'version': 'bb', 'timestamp': 1467147654}, None), 63 ('11', {'version': 'bb', 'timestamp': 1467146654}, 64 {'result': 'PASSED', 'passed': True}), 65 ('10', {'version': 'aa', 'timestamp': 1467136654}, 66 {'result': 'FAILED', 'passed': False})], 67 'e2e': [('47', {'version': 'bb', 'timestamp': '1467147654'}, 68 {'result': '[UNSET]', 'passed': False}), 69 ('46', {'version': 'aa', 'timestamp': '1467136700'}, 70 {'result': '[UNSET]', 'passed': False})] 71 } 72 73 def setUp(self): 74 self.init_stubs() 75 76 def init_pr_directory(self): 77 gcs_async_test.install_handler(self.testbed.get_stub('urlfetch'), 78 {'123/': ['build', 'e2e'], 79 '123/build/': ['11', '10', '12'], # out of order 80 '123/e2e/': ['47', '46']}) 81 82 for job, builds in self.BUILDS.iteritems(): 83 for build, started, finished in builds: 84 path = '/kubernetes-jenkins/pr-logs/pull/123/%s/%s/' % (job, build) 85 if started: 86 write(path + 'started.json', started) 87 if finished: 88 write(path + 'finished.json', finished) 89 90 def test_pr_builds(self): 91 self.init_pr_directory() 92 org, repo = view_pr.org_repo('', 93 app.app.config['default_org'], 94 app.app.config['default_repo'], 95 ) 96 builds = view_pr.pr_builds(view_pr.pr_path(org, repo, '123', 97 app.app.config['default_repo'], 98 app.app.config['default_repo'], 99 app.app.config['default_external_services']['gcs_pull_prefix'], 100 )) 101 self.assertEqual(builds, self.BUILDS) 102 103 def test_pr_handler(self): 104 self.init_pr_directory() 105 response = app.get('/pr/123') 106 self.assertIn('e2e/47', response) 107 self.assertIn('PASSED', response) 108 self.assertIn('colspan="3"', response) # header 109 self.assertIn('github.com/kubernetes/kubernetes/pull/123', response) 110 self.assertIn('28 20:44', response) 111 112 def test_pr_handler_missing(self): 113 gcs_async_test.install_handler(self.testbed.get_stub('urlfetch'), 114 {'124/': []}) 115 response = app.get('/pr/124') 116 self.assertIn('No Results', response) 117 118 def test_pr_build_log_redirect(self): 119 path = '123/some-job/55/build-log.txt' 120 response = app.get('/pr/' + path) 121 self.assertEqual(response.status_code, 302) 122 self.assertIn('https://storage.googleapis.com', response.location) 123 self.assertIn(path, response.location) 124 125 126 def make_pr(number, involved, payload, repo='kubernetes/kubernetes'): 127 payload.setdefault('attn', {}) 128 payload.setdefault('assignees', []) 129 payload.setdefault('author', involved[0]) 130 payload.setdefault('labels', {}) 131 digest = models.GHIssueDigest.make(repo, number, is_pr=True, is_open=True, 132 involved=involved, payload=payload, updated_at=datetime.datetime.now()) 133 digest.put() 134 135 136 class TestDashboard(main_test.TestBase): 137 def setUp(self): 138 app.reset() 139 self.init_stubs() 140 141 def test_empty(self): 142 resp = app.get('/pr/all') 143 self.assertIn('No Results', resp) 144 resp = app.get('/pr/nobody') 145 self.assertIn('No Results', resp) 146 147 def test_all(self): 148 make_pr(12, ['foo'], {'title': 'first'}, 'google/cadvisor') 149 make_pr(13, ['bar'], {'title': 'second'}, 'kubernetes/kubernetes') 150 resp = app.get('/pr/all') 151 self.assertIn('Open Kubernetes PRs', resp) 152 self.assertIn('first', resp) 153 self.assertIn('second', resp) 154 155 def test_json(self): 156 make_pr(12, ['a'], {'title': 'b'}, 'c/d') 157 resp = app.get('/pr/all?format=json') 158 self.assertEqual(resp.headers['Content-Type'], 'application/json') 159 self.assertEqual(len(resp.json), 1) 160 pr = resp.json[0] 161 self.assertEqual(pr['involved'], ['a']) 162 self.assertEqual(pr['number'], 12) 163 self.assertEqual(pr['repo'], 'c/d') 164 165 def test_one_entry(self): 166 make_pr(123, ['user'], {'attn': {'user': 'fix tests'}}) 167 resp = app.get('/pr/user') 168 self.assertIn('123', resp) 169 170 def test_case_insensitive(self): 171 "Individual PR pages are case insensitive." 172 make_pr(123, ['user'], {'attn': {'User': 'fix tests'}}) 173 resp = app.get('/pr/UseR') 174 self.assertIn('123', resp) 175 self.assertIn('Needs Attention (1)', resp) 176 177 def test_milestone(self): 178 "Milestone links filter by milestone." 179 make_pr(123, ['user'], {'attn': {'User': 'fix tests'}}) 180 make_pr(124, ['user'], {'attn': {'user': 'fix tests'}, 'milestone': 'v1.24'}) 181 resp = app.get('/pr/user') 182 self.assertIn('v1.24', resp) 183 self.assertIn('123', resp) 184 self.assertIn('124', resp) 185 resp = app.get('/pr/user?milestone=v1.24') 186 # Don't match timestamps that happen to include "123". 187 self.assertNotRegexpMatches(str(resp), r'\b123\b') 188 self.assertIn('124', resp) 189 190 @staticmethod 191 def make_session(**kwargs): 192 # set the session cookie directly (easier than the full login flow) 193 serializer = securecookie.SecureCookieSerializer( 194 app.app.config['webapp2_extras.sessions']['secret_key']) 195 return serializer.serialize('session', kwargs) 196 197 def test_me(self): 198 make_pr(124, ['human'], {'title': 'huge pr!'}) 199 200 # no cookie: we get redirected 201 resp = app.get('/pr') 202 self.assertEqual(resp.status_code, 302) 203 self.assertEqual(resp.location, 'http://localhost/github_auth/pr') 204 205 # we have a cookie now: we should get results for 'human' 206 cookie = self.make_session(user='human') 207 resp = app.get('/pr', headers={'Cookie': 'session=%s' % cookie}) 208 self.assertEqual(resp.status_code, 200) 209 self.assertIn('huge pr!', resp) 210 211 def test_pr_links_user(self): 212 "Individual PR pages grab digest information" 213 gcs_async_test.install_handler(self.testbed.get_stub('urlfetch'), 214 {'12345/': []}) 215 make_pr(12345, ['human'], {'title': 'huge pr!'}) 216 resp = app.get('/pr/12345') 217 self.assertIn('href="/pr/human"', resp) 218 self.assertIn('huge pr!', resp) 219 220 def test_build_links_user(self): 221 "Build pages show PR information" 222 make_pr(12345, ['human'], {'title': 'huge pr!'}) 223 build_dir = '/kubernetes-jenkins/pr-logs/pull/12345/e2e/5/' 224 write(build_dir + 'started.json', '{}') 225 resp = app.get('/build' + build_dir) 226 self.assertIn('href="/pr/human"', resp) 227 self.assertIn('huge pr!', resp) 228 229 def test_acks(self): 230 app.get('/') # initialize session secrets 231 232 make_pr(124, ['human'], {'title': 'huge pr', 'attn': {'human': 'help#123#456'}}, repo='k/k') 233 cookie = self.make_session(user='human') 234 headers = {'Cookie': 'session=%s' % cookie} 235 236 def expect_count(count): 237 resp = app.get('/pr', headers=headers) 238 self.assertEqual(resp.body.count('huge pr'), count) 239 240 # PR should appear twice 241 expect_count(2) 242 243 # Ack the PR... 244 ack_params = {'command': 'ack', 'repo': 'k/k', 'number': 124, 'latest': 456} 245 app.post_json('/pr', ack_params, headers=headers) 246 expect_count(1) 247 self.assertEqual(view_pr.get_acks('human', []), {'k/k 124': 456}) 248 249 # Clear the ack 250 app.post_json('/pr', {'command': 'ack-clear'}, headers=headers) 251 expect_count(2) 252 self.assertEqual(view_pr.get_acks('human', []), {}) 253 254 # Ack with an older latest 255 ack_params['latest'] = 123 256 app.post_json('/pr', ack_params, headers=headers) 257 expect_count(2) 258 259 260 if __name__ == '__main__': 261 unittest.main()