James E. Blair | 4f56826 | 2017-12-21 09:18:21 -0800 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 2 | |
| 3 | # Copyright 2014 Hewlett-Packard Development Company, L.P. |
| 4 | # Copyright 2014 Rackspace Australia |
| 5 | # |
| 6 | # Licensed under the Apache License, Version 2.0 (the "License"); you may |
| 7 | # not use this file except in compliance with the License. You may obtain |
| 8 | # a copy of the License at |
| 9 | # |
| 10 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 11 | # |
| 12 | # Unless required by applicable law or agreed to in writing, software |
| 13 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| 14 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| 15 | # License for the specific language governing permissions and limitations |
| 16 | # under the License. |
| 17 | |
| 18 | import asyncio |
| 19 | import threading |
| 20 | import os |
| 21 | import json |
| 22 | import urllib |
| 23 | import time |
| 24 | import socket |
| 25 | from unittest import skip |
| 26 | |
| 27 | import webob |
| 28 | |
| 29 | import zuul.web |
| 30 | |
| 31 | from tests.base import ZuulTestCase, FIXTURE_DIR |
| 32 | |
| 33 | |
| 34 | class TestWeb(ZuulTestCase): |
| 35 | tenant_config_file = 'config/single-tenant/main.yaml' |
| 36 | |
| 37 | def setUp(self): |
| 38 | super(TestWeb, self).setUp() |
| 39 | self.executor_server.hold_jobs_in_build = True |
| 40 | A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A') |
| 41 | A.addApproval('Code-Review', 2) |
| 42 | self.fake_gerrit.addEvent(A.addApproval('Approved', 1)) |
| 43 | B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B') |
| 44 | B.addApproval('Code-Review', 2) |
| 45 | self.fake_gerrit.addEvent(B.addApproval('Approved', 1)) |
| 46 | self.waitUntilSettled() |
| 47 | |
| 48 | # Start the web server |
| 49 | self.web = zuul.web.ZuulWeb( |
| 50 | listen_address='127.0.0.1', listen_port=0, |
| 51 | gear_server='127.0.0.1', gear_port=self.gearman_server.port) |
| 52 | loop = asyncio.new_event_loop() |
| 53 | loop.set_debug(True) |
| 54 | ws_thread = threading.Thread(target=self.web.run, args=(loop,)) |
| 55 | ws_thread.start() |
| 56 | self.addCleanup(loop.close) |
| 57 | self.addCleanup(ws_thread.join) |
| 58 | self.addCleanup(self.web.stop) |
| 59 | |
| 60 | self.host = 'localhost' |
| 61 | # Wait until web server is started |
| 62 | while True: |
| 63 | time.sleep(0.1) |
| 64 | if self.web.server is None: |
| 65 | continue |
| 66 | self.port = self.web.server.sockets[0].getsockname()[1] |
| 67 | print(self.host, self.port) |
| 68 | try: |
| 69 | with socket.create_connection((self.host, self.port)): |
| 70 | break |
| 71 | except ConnectionRefusedError: |
| 72 | pass |
| 73 | |
| 74 | def tearDown(self): |
| 75 | self.executor_server.hold_jobs_in_build = False |
| 76 | self.executor_server.release() |
| 77 | self.waitUntilSettled() |
| 78 | super(TestWeb, self).tearDown() |
| 79 | |
| 80 | def test_web_status(self): |
| 81 | "Test that we can filter to only certain changes in the webapp." |
| 82 | |
| 83 | req = urllib.request.Request( |
| 84 | "http://localhost:%s/tenant-one/status.json" % self.port) |
| 85 | f = urllib.request.urlopen(req) |
| 86 | data = json.loads(f.read().decode('utf8')) |
| 87 | |
| 88 | self.assertIn('pipelines', data) |
| 89 | |
| 90 | def test_web_bad_url(self): |
| 91 | # do we 404 correctly |
| 92 | req = urllib.request.Request( |
| 93 | "http://localhost:%s/status/foo" % self.port) |
| 94 | self.assertRaises(urllib.error.HTTPError, urllib.request.urlopen, req) |
| 95 | |
| 96 | @skip("This is not supported by zuul-web") |
| 97 | def test_web_find_change(self): |
| 98 | # can we filter by change id |
| 99 | req = urllib.request.Request( |
| 100 | "http://localhost:%s/tenant-one/status/change/1,1" % self.port) |
| 101 | f = urllib.request.urlopen(req) |
| 102 | data = json.loads(f.read().decode('utf8')) |
| 103 | |
| 104 | self.assertEqual(1, len(data), data) |
| 105 | self.assertEqual("org/project", data[0]['project']) |
| 106 | |
| 107 | req = urllib.request.Request( |
| 108 | "http://localhost:%s/tenant-one/status/change/2,1" % self.port) |
| 109 | f = urllib.request.urlopen(req) |
| 110 | data = json.loads(f.read().decode('utf8')) |
| 111 | |
| 112 | self.assertEqual(1, len(data), data) |
| 113 | self.assertEqual("org/project1", data[0]['project'], data) |
| 114 | |
| 115 | def test_web_keys(self): |
| 116 | with open(os.path.join(FIXTURE_DIR, 'public.pem'), 'rb') as f: |
| 117 | public_pem = f.read() |
| 118 | |
| 119 | req = urllib.request.Request( |
| 120 | "http://localhost:%s/tenant-one/org/project.pub" % |
| 121 | self.port) |
| 122 | f = urllib.request.urlopen(req) |
| 123 | self.assertEqual(f.read(), public_pem) |
| 124 | |
| 125 | @skip("This may not apply to zuul-web") |
| 126 | def test_web_custom_handler(self): |
| 127 | def custom_handler(path, tenant_name, request): |
| 128 | return webob.Response(body='ok') |
| 129 | |
| 130 | self.webapp.register_path('/custom', custom_handler) |
| 131 | req = urllib.request.Request( |
| 132 | "http://localhost:%s/custom" % self.port) |
| 133 | f = urllib.request.urlopen(req) |
| 134 | self.assertEqual(b'ok', f.read()) |
| 135 | |
| 136 | self.webapp.unregister_path('/custom') |
| 137 | self.assertRaises(urllib.error.HTTPError, urllib.request.urlopen, req) |
| 138 | |
| 139 | @skip("This returns a 500") |
| 140 | def test_web_404_on_unknown_tenant(self): |
| 141 | req = urllib.request.Request( |
| 142 | "http://localhost:{}/non-tenant/status.json".format(self.port)) |
| 143 | e = self.assertRaises( |
| 144 | urllib.error.HTTPError, urllib.request.urlopen, req) |
| 145 | self.assertEqual(404, e.code) |