summaryrefslogtreecommitdiffstats
path: root/testing/mozbase/mozhttpd/tests
diff options
context:
space:
mode:
Diffstat (limited to 'testing/mozbase/mozhttpd/tests')
-rw-r--r--testing/mozbase/mozhttpd/tests/api.py266
-rw-r--r--testing/mozbase/mozhttpd/tests/baseurl.py19
-rw-r--r--testing/mozbase/mozhttpd/tests/basic.py46
-rw-r--r--testing/mozbase/mozhttpd/tests/filelisting.py43
-rw-r--r--testing/mozbase/mozhttpd/tests/manifest.ini6
-rw-r--r--testing/mozbase/mozhttpd/tests/paths.py77
-rw-r--r--testing/mozbase/mozhttpd/tests/requestlog.py41
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()