diff options
Diffstat (limited to 'testing/mozbase/mozhttpd/tests')
-rw-r--r-- | testing/mozbase/mozhttpd/tests/api.py | 266 | ||||
-rw-r--r-- | testing/mozbase/mozhttpd/tests/baseurl.py | 19 | ||||
-rw-r--r-- | testing/mozbase/mozhttpd/tests/basic.py | 46 | ||||
-rw-r--r-- | testing/mozbase/mozhttpd/tests/filelisting.py | 43 | ||||
-rw-r--r-- | testing/mozbase/mozhttpd/tests/manifest.ini | 6 | ||||
-rw-r--r-- | testing/mozbase/mozhttpd/tests/paths.py | 77 | ||||
-rw-r--r-- | testing/mozbase/mozhttpd/tests/requestlog.py | 41 |
7 files changed, 498 insertions, 0 deletions
diff --git a/testing/mozbase/mozhttpd/tests/api.py b/testing/mozbase/mozhttpd/tests/api.py new file mode 100644 index 000000000..b785ac5ef --- /dev/null +++ b/testing/mozbase/mozhttpd/tests/api.py @@ -0,0 +1,266 @@ +#!/usr/bin/env python + +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at http://mozilla.org/MPL/2.0/. + +import mozfile +import mozhttpd +import urllib2 +import os +import unittest +import json +import tempfile + +here = os.path.dirname(os.path.abspath(__file__)) + + +class ApiTest(unittest.TestCase): + resource_get_called = 0 + resource_post_called = 0 + resource_del_called = 0 + + @mozhttpd.handlers.json_response + def resource_get(self, request, objid): + self.resource_get_called += 1 + return (200, {'called': self.resource_get_called, + 'id': objid, + 'query': request.query}) + + @mozhttpd.handlers.json_response + def resource_post(self, request): + self.resource_post_called += 1 + return (201, {'called': self.resource_post_called, + 'data': json.loads(request.body), + 'query': request.query}) + + @mozhttpd.handlers.json_response + def resource_del(self, request, objid): + self.resource_del_called += 1 + return (200, {'called': self.resource_del_called, + 'id': objid, + 'query': request.query}) + + def get_url(self, path, server_port, querystr): + url = "http://127.0.0.1:%s%s" % (server_port, path) + if querystr: + url += "?%s" % querystr + return url + + def try_get(self, server_port, querystr): + self.resource_get_called = 0 + + f = urllib2.urlopen(self.get_url('/api/resource/1', server_port, querystr)) + try: + self.assertEqual(f.getcode(), 200) + except AttributeError: + pass # python 2.4 + self.assertEqual(json.loads(f.read()), {'called': 1, 'id': str(1), 'query': querystr}) + self.assertEqual(self.resource_get_called, 1) + + def try_post(self, server_port, querystr): + self.resource_post_called = 0 + + postdata = {'hamburgers': '1234'} + try: + f = urllib2.urlopen(self.get_url('/api/resource/', server_port, querystr), + data=json.dumps(postdata)) + except urllib2.HTTPError as e: + # python 2.4 + self.assertEqual(e.code, 201) + body = e.fp.read() + else: + self.assertEqual(f.getcode(), 201) + body = f.read() + self.assertEqual(json.loads(body), {'called': 1, + 'data': postdata, + 'query': querystr}) + self.assertEqual(self.resource_post_called, 1) + + def try_del(self, server_port, querystr): + self.resource_del_called = 0 + + opener = urllib2.build_opener(urllib2.HTTPHandler) + request = urllib2.Request(self.get_url('/api/resource/1', server_port, querystr)) + request.get_method = lambda: 'DEL' + f = opener.open(request) + + try: + self.assertEqual(f.getcode(), 200) + except AttributeError: + pass # python 2.4 + self.assertEqual(json.loads(f.read()), {'called': 1, 'id': str(1), 'query': querystr}) + self.assertEqual(self.resource_del_called, 1) + + def test_api(self): + httpd = mozhttpd.MozHttpd(port=0, + urlhandlers=[{'method': 'GET', + 'path': '/api/resource/([^/]+)/?', + 'function': self.resource_get}, + {'method': 'POST', + 'path': '/api/resource/?', + 'function': self.resource_post}, + {'method': 'DEL', + 'path': '/api/resource/([^/]+)/?', + 'function': self.resource_del} + ]) + httpd.start(block=False) + + server_port = httpd.httpd.server_port + + # GET + self.try_get(server_port, '') + self.try_get(server_port, '?foo=bar') + + # POST + self.try_post(server_port, '') + self.try_post(server_port, '?foo=bar') + + # DEL + self.try_del(server_port, '') + self.try_del(server_port, '?foo=bar') + + # GET: By default we don't serve any files if we just define an API + exception_thrown = False + try: + urllib2.urlopen(self.get_url('/', server_port, None)) + except urllib2.HTTPError as e: + self.assertEqual(e.code, 404) + exception_thrown = True + self.assertTrue(exception_thrown) + + def test_nonexistent_resources(self): + # Create a server with a placeholder handler so we don't fall back + # to serving local files + httpd = mozhttpd.MozHttpd(port=0) + httpd.start(block=False) + server_port = httpd.httpd.server_port + + # GET: Return 404 for non-existent endpoint + exception_thrown = False + try: + urllib2.urlopen(self.get_url('/api/resource/', server_port, None)) + except urllib2.HTTPError as e: + self.assertEqual(e.code, 404) + exception_thrown = True + self.assertTrue(exception_thrown) + + # POST: POST should also return 404 + exception_thrown = False + try: + urllib2.urlopen(self.get_url('/api/resource/', server_port, None), + data=json.dumps({})) + except urllib2.HTTPError as e: + self.assertEqual(e.code, 404) + exception_thrown = True + self.assertTrue(exception_thrown) + + # DEL: DEL should also return 404 + exception_thrown = False + try: + opener = urllib2.build_opener(urllib2.HTTPHandler) + request = urllib2.Request(self.get_url('/api/resource/', server_port, + None)) + request.get_method = lambda: 'DEL' + opener.open(request) + except urllib2.HTTPError: + self.assertEqual(e.code, 404) + exception_thrown = True + self.assertTrue(exception_thrown) + + def test_api_with_docroot(self): + httpd = mozhttpd.MozHttpd(port=0, docroot=here, + urlhandlers=[{'method': 'GET', + 'path': '/api/resource/([^/]+)/?', + 'function': self.resource_get}]) + httpd.start(block=False) + server_port = httpd.httpd.server_port + + # We defined a docroot, so we expect a directory listing + f = urllib2.urlopen(self.get_url('/', server_port, None)) + try: + self.assertEqual(f.getcode(), 200) + except AttributeError: + pass # python 2.4 + self.assertTrue('Directory listing for' in f.read()) + + # Make sure API methods still work + self.try_get(server_port, '') + self.try_get(server_port, '?foo=bar') + + +class ProxyTest(unittest.TestCase): + + def tearDown(self): + # reset proxy opener in case it changed + urllib2.install_opener(None) + + def test_proxy(self): + docroot = tempfile.mkdtemp() + self.addCleanup(mozfile.remove, docroot) + hosts = ('mozilla.com', 'mozilla.org') + unproxied_host = 'notmozilla.org' + + def url(host): return 'http://%s/' % host + + index_filename = 'index.html' + + def index_contents(host): return '%s index' % host + + index = file(os.path.join(docroot, index_filename), 'w') + index.write(index_contents('*')) + index.close() + + httpd = mozhttpd.MozHttpd(port=0, docroot=docroot) + httpd.start(block=False) + server_port = httpd.httpd.server_port + + proxy_support = urllib2.ProxyHandler({'http': 'http://127.0.0.1:%d' % + server_port}) + urllib2.install_opener(urllib2.build_opener(proxy_support)) + + for host in hosts: + f = urllib2.urlopen(url(host)) + try: + self.assertEqual(f.getcode(), 200) + except AttributeError: + pass # python 2.4 + self.assertEqual(f.read(), index_contents('*')) + + httpd.stop() + + # test separate directories per host + + httpd = mozhttpd.MozHttpd(port=0, docroot=docroot, proxy_host_dirs=True) + httpd.start(block=False) + server_port = httpd.httpd.server_port + + proxy_support = urllib2.ProxyHandler({'http': 'http://127.0.0.1:%d' % + server_port}) + urllib2.install_opener(urllib2.build_opener(proxy_support)) + + # set up dirs + for host in hosts: + os.mkdir(os.path.join(docroot, host)) + file(os.path.join(docroot, host, index_filename), 'w') \ + .write(index_contents(host)) + + for host in hosts: + f = urllib2.urlopen(url(host)) + try: + self.assertEqual(f.getcode(), 200) + except AttributeError: + pass # python 2.4 + self.assertEqual(f.read(), index_contents(host)) + + exc = None + try: + urllib2.urlopen(url(unproxied_host)) + except urllib2.HTTPError as e: + exc = e + self.assertNotEqual(exc, None) + self.assertEqual(exc.code, 404) + + +if __name__ == '__main__': + unittest.main() diff --git a/testing/mozbase/mozhttpd/tests/baseurl.py b/testing/mozbase/mozhttpd/tests/baseurl.py new file mode 100644 index 000000000..0e971e6b2 --- /dev/null +++ b/testing/mozbase/mozhttpd/tests/baseurl.py @@ -0,0 +1,19 @@ +import mozhttpd +import unittest + + +class BaseUrlTest(unittest.TestCase): + + def test_base_url(self): + httpd = mozhttpd.MozHttpd(port=0) + self.assertEqual(httpd.get_url(), None) + httpd.start(block=False) + self.assertEqual("http://127.0.0.1:%s/" % httpd.httpd.server_port, + httpd.get_url()) + self.assertEqual("http://127.0.0.1:%s/cheezburgers.html" % + httpd.httpd.server_port, + httpd.get_url(path="/cheezburgers.html")) + httpd.stop() + +if __name__ == '__main__': + unittest.main() diff --git a/testing/mozbase/mozhttpd/tests/basic.py b/testing/mozbase/mozhttpd/tests/basic.py new file mode 100644 index 000000000..8d64b4332 --- /dev/null +++ b/testing/mozbase/mozhttpd/tests/basic.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python + +import mozhttpd +import mozfile +import os +import tempfile +import unittest + + +class TestBasic(unittest.TestCase): + """ Test basic Mozhttpd capabilites """ + + def test_basic(self): + """ Test mozhttpd can serve files """ + + tempdir = tempfile.mkdtemp() + + # sizes is a dict of the form: name -> [size, binary_string, filepath] + sizes = {'small': [128], 'large': [16384]} + + for k in sizes.keys(): + # Generate random binary string + sizes[k].append(os.urandom(sizes[k][0])) + + # Add path of file with binary string to list + fpath = os.path.join(tempdir, k) + sizes[k].append(fpath) + + # Write binary string to file + with open(fpath, 'wb') as f: + f.write(sizes[k][1]) + + server = mozhttpd.MozHttpd(docroot=tempdir) + server.start() + server_url = server.get_url() + + # Retrieve file and check contents matchup + for k in sizes.keys(): + retrieved_content = mozfile.load(server_url + k).read() + self.assertEqual(retrieved_content, sizes[k][1]) + + # Cleanup tempdir and related files + mozfile.rmtree(tempdir) + +if __name__ == '__main__': + unittest.main() diff --git a/testing/mozbase/mozhttpd/tests/filelisting.py b/testing/mozbase/mozhttpd/tests/filelisting.py new file mode 100644 index 000000000..6abea757f --- /dev/null +++ b/testing/mozbase/mozhttpd/tests/filelisting.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python + +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at http://mozilla.org/MPL/2.0/. + +import mozhttpd +import urllib2 +import os +import unittest +import re + +here = os.path.dirname(os.path.abspath(__file__)) + + +class FileListingTest(unittest.TestCase): + + def check_filelisting(self, path=''): + filelist = os.listdir(here) + + httpd = mozhttpd.MozHttpd(port=0, docroot=here) + httpd.start(block=False) + f = urllib2.urlopen("http://%s:%s/%s" % ('127.0.0.1', httpd.httpd.server_port, path)) + for line in f.readlines(): + webline = re.sub('\<[a-zA-Z0-9\-\_\.\=\"\'\/\\\%\!\@\#\$\^\&\*\(\) ]*\>', + '', line.strip('\n')).strip('/').strip().strip('@') + + if webline and not webline.startswith("Directory listing for"): + self.assertTrue(webline in filelist, + "File %s in dir listing corresponds to a file" % webline) + filelist.remove(webline) + self.assertFalse( + filelist, "Should have no items in filelist (%s) unaccounted for" % filelist) + + def test_filelist(self): + self.check_filelisting() + + def test_filelist_params(self): + self.check_filelisting('?foo=bar&fleem=&foo=fleem') + + +if __name__ == '__main__': + unittest.main() diff --git a/testing/mozbase/mozhttpd/tests/manifest.ini b/testing/mozbase/mozhttpd/tests/manifest.ini new file mode 100644 index 000000000..3f3d42d9b --- /dev/null +++ b/testing/mozbase/mozhttpd/tests/manifest.ini @@ -0,0 +1,6 @@ +[api.py] +[baseurl.py] +[basic.py] +[filelisting.py] +[paths.py] +[requestlog.py] diff --git a/testing/mozbase/mozhttpd/tests/paths.py b/testing/mozbase/mozhttpd/tests/paths.py new file mode 100644 index 000000000..45ae40144 --- /dev/null +++ b/testing/mozbase/mozhttpd/tests/paths.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python + +# Any copyright is dedicated to the Public Domain. +# http://creativecommons.org/publicdomain/zero/1.0/ + +from mozfile import TemporaryDirectory +import mozhttpd +import os +import unittest +import urllib2 + + +class PathTest(unittest.TestCase): + + def try_get(self, url, expected_contents): + f = urllib2.urlopen(url) + self.assertEqual(f.getcode(), 200) + self.assertEqual(f.read(), expected_contents) + + def try_get_expect_404(self, url): + with self.assertRaises(urllib2.HTTPError) as cm: + urllib2.urlopen(url) + self.assertEqual(404, cm.exception.code) + + def test_basic(self): + """Test that requests to docroot and a path mapping work as expected.""" + with TemporaryDirectory() as d1, TemporaryDirectory() as d2: + open(os.path.join(d1, "test1.txt"), "w").write("test 1 contents") + open(os.path.join(d2, "test2.txt"), "w").write("test 2 contents") + httpd = mozhttpd.MozHttpd(port=0, + docroot=d1, + path_mappings={'/files': d2} + ) + httpd.start(block=False) + self.try_get(httpd.get_url("/test1.txt"), "test 1 contents") + self.try_get(httpd.get_url("/files/test2.txt"), "test 2 contents") + self.try_get_expect_404(httpd.get_url("/files/test2_nope.txt")) + httpd.stop() + + def test_substring_mappings(self): + """Test that a path mapping that's a substring of another works.""" + with TemporaryDirectory() as d1, TemporaryDirectory() as d2: + open(os.path.join(d1, "test1.txt"), "w").write("test 1 contents") + open(os.path.join(d2, "test2.txt"), "w").write("test 2 contents") + httpd = mozhttpd.MozHttpd(port=0, + path_mappings={'/abcxyz': d1, + '/abc': d2, } + ) + httpd.start(block=False) + self.try_get(httpd.get_url("/abcxyz/test1.txt"), "test 1 contents") + self.try_get(httpd.get_url("/abc/test2.txt"), "test 2 contents") + httpd.stop() + + def test_multipart_path_mapping(self): + """Test that a path mapping with multiple directories works.""" + with TemporaryDirectory() as d1: + open(os.path.join(d1, "test1.txt"), "w").write("test 1 contents") + httpd = mozhttpd.MozHttpd(port=0, + path_mappings={'/abc/def/ghi': d1} + ) + httpd.start(block=False) + self.try_get(httpd.get_url("/abc/def/ghi/test1.txt"), "test 1 contents") + self.try_get_expect_404(httpd.get_url("/abc/test1.txt")) + self.try_get_expect_404(httpd.get_url("/abc/def/test1.txt")) + httpd.stop() + + def test_no_docroot(self): + """Test that path mappings with no docroot work.""" + with TemporaryDirectory() as d1: + httpd = mozhttpd.MozHttpd(port=0, + path_mappings={'/foo': d1}) + httpd.start(block=False) + self.try_get_expect_404(httpd.get_url()) + httpd.stop() + +if __name__ == '__main__': + unittest.main() diff --git a/testing/mozbase/mozhttpd/tests/requestlog.py b/testing/mozbase/mozhttpd/tests/requestlog.py new file mode 100644 index 000000000..bf2c59ec3 --- /dev/null +++ b/testing/mozbase/mozhttpd/tests/requestlog.py @@ -0,0 +1,41 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at http://mozilla.org/MPL/2.0/. + +import mozhttpd +import urllib2 +import os +import unittest + +here = os.path.dirname(os.path.abspath(__file__)) + + +class RequestLogTest(unittest.TestCase): + + def check_logging(self, log_requests=False): + + httpd = mozhttpd.MozHttpd(port=0, docroot=here, log_requests=log_requests) + httpd.start(block=False) + url = "http://%s:%s/" % ('127.0.0.1', httpd.httpd.server_port) + f = urllib2.urlopen(url) + f.read() + + return httpd.request_log + + def test_logging_enabled(self): + request_log = self.check_logging(log_requests=True) + + self.assertEqual(len(request_log), 1) + + log_entry = request_log[0] + self.assertEqual(log_entry['method'], 'GET') + self.assertEqual(log_entry['path'], '/') + self.assertEqual(type(log_entry['time']), float) + + def test_logging_disabled(self): + request_log = self.check_logging(log_requests=False) + + self.assertEqual(len(request_log), 0) + +if __name__ == '__main__': + unittest.main() |