183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehfrom __future__ import nested_scopes    # Backward compat for 2.1
283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehfrom unittest import TestCase
383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehfrom wsgiref.util import setup_testing_defaults
483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehfrom wsgiref.headers import Headers
583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehfrom wsgiref.handlers import BaseHandler, BaseCGIHandler
683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehfrom wsgiref import util
783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehfrom wsgiref.validate import validator
883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehfrom wsgiref.simple_server import WSGIServer, WSGIRequestHandler, demo_app
983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehfrom wsgiref.simple_server import make_server
1083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehfrom StringIO import StringIO
1183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehfrom SocketServer import BaseServer
1283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport os
1383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport re
1483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport sys
1583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
1683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehfrom test import test_support
1783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
1883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass MockServer(WSGIServer):
1983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    """Non-socket HTTP server"""
2083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
2183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __init__(self, server_address, RequestHandlerClass):
2283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        BaseServer.__init__(self, server_address, RequestHandlerClass)
2383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.server_bind()
2483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
2583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def server_bind(self):
2683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        host, port = self.server_address
2783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.server_name = host
2883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.server_port = port
2983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.setup_environ()
3083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
3183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
3283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass MockHandler(WSGIRequestHandler):
3383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    """Non-socket HTTP handler"""
3483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def setup(self):
3583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.connection = self.request
3683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.rfile, self.wfile = self.connection
3783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
3883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def finish(self):
3983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        pass
4083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
4183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
4283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef hello_app(environ,start_response):
4383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    start_response("200 OK", [
4483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        ('Content-Type','text/plain'),
4583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        ('Date','Mon, 05 Jun 2006 18:49:54 GMT')
4683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    ])
4783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    return ["Hello, world!"]
4883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
4983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef run_amock(app=hello_app, data="GET / HTTP/1.0\n\n"):
5083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    server = make_server("", 80, app, MockServer, MockHandler)
5183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    inp, out, err, olderr = StringIO(data), StringIO(), StringIO(), sys.stderr
5283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    sys.stderr = err
5383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
5483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    try:
5583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        server.finish_request((inp,out), ("127.0.0.1",8888))
5683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    finally:
5783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        sys.stderr = olderr
5883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
5983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    return out.getvalue(), err.getvalue()
6083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
6183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
6283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef compare_generic_iter(make_it,match):
6383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    """Utility to compare a generic 2.1/2.2+ iterator with an iterable
6483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
6583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    If running under Python 2.2+, this tests the iterator using iter()/next(),
6683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    as well as __getitem__.  'make_it' must be a function returning a fresh
6783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    iterator to be tested (since this may test the iterator twice)."""
6883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
6983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    it = make_it()
7083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    n = 0
7183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    for item in match:
7283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if not it[n]==item: raise AssertionError
7383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        n+=1
7483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    try:
7583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        it[n]
7683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    except IndexError:
7783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        pass
7883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    else:
7983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        raise AssertionError("Too many items from __getitem__",it)
8083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
8183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    try:
8283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        iter, StopIteration
8383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    except NameError:
8483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        pass
8583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    else:
8683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # Only test iter mode under 2.2+
8783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        it = make_it()
8883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if not iter(it) is it: raise AssertionError
8983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        for item in match:
9083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if not it.next()==item: raise AssertionError
9183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        try:
9283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            it.next()
9383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        except StopIteration:
9483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            pass
9583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        else:
9683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            raise AssertionError("Too many items from .next()",it)
9783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
9883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
9983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass IntegrationTests(TestCase):
10083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
10183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def check_hello(self, out, has_length=True):
10283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(out,
10383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            "HTTP/1.0 200 OK\r\n"
10483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            "Server: WSGIServer/0.1 Python/"+sys.version.split()[0]+"\r\n"
10583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            "Content-Type: text/plain\r\n"
10683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            "Date: Mon, 05 Jun 2006 18:49:54 GMT\r\n" +
10783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            (has_length and  "Content-Length: 13\r\n" or "") +
10883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            "\r\n"
10983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            "Hello, world!"
11083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        )
11183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
11283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def test_plain_hello(self):
11383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        out, err = run_amock()
11483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.check_hello(out)
11583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
11683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def test_validated_hello(self):
11783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        out, err = run_amock(validator(hello_app))
11883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # the middleware doesn't support len(), so content-length isn't there
11983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.check_hello(out, has_length=False)
12083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
12183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def test_simple_validation_error(self):
12283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        def bad_app(environ,start_response):
12383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            start_response("200 OK", ('Content-Type','text/plain'))
12483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return ["Hello, world!"]
12583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        out, err = run_amock(validator(bad_app))
12683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertTrue(out.endswith(
12783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            "A server error occurred.  Please contact the administrator."
12883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        ))
12983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(
13083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            err.splitlines()[-2],
13183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            "AssertionError: Headers (('Content-Type', 'text/plain')) must"
13283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            " be of type list: <type 'tuple'>"
13383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        )
13483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
13583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
13683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass UtilityTests(TestCase):
13783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
13883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def checkShift(self,sn_in,pi_in,part,sn_out,pi_out):
13983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        env = {'SCRIPT_NAME':sn_in,'PATH_INFO':pi_in}
14083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        util.setup_testing_defaults(env)
14183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(util.shift_path_info(env),part)
14283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(env['PATH_INFO'],pi_out)
14383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(env['SCRIPT_NAME'],sn_out)
14483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return env
14583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
14683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def checkDefault(self, key, value, alt=None):
14783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # Check defaulting when empty
14883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        env = {}
14983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        util.setup_testing_defaults(env)
15083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if isinstance(value, StringIO):
15183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.assertIsInstance(env[key], StringIO)
15283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        else:
15383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.assertEqual(env[key], value)
15483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
15583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # Check existing value
15683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        env = {key:alt}
15783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        util.setup_testing_defaults(env)
15883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertTrue(env[key] is alt)
15983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
16083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def checkCrossDefault(self,key,value,**kw):
16183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        util.setup_testing_defaults(kw)
16283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(kw[key],value)
16383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
16483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def checkAppURI(self,uri,**kw):
16583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        util.setup_testing_defaults(kw)
16683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(util.application_uri(kw),uri)
16783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
16883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def checkReqURI(self,uri,query=1,**kw):
16983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        util.setup_testing_defaults(kw)
17083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(util.request_uri(kw,query),uri)
17183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
17283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def checkFW(self,text,size,match):
17383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
17483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        def make_it(text=text,size=size):
17583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return util.FileWrapper(StringIO(text),size)
17683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
17783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        compare_generic_iter(make_it,match)
17883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
17983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        it = make_it()
18083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertFalse(it.filelike.closed)
18183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
18283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        for item in it:
18383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            pass
18483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
18583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertFalse(it.filelike.closed)
18683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
18783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        it.close()
18883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertTrue(it.filelike.closed)
18983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
19083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def testSimpleShifts(self):
19183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.checkShift('','/', '', '/', '')
19283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.checkShift('','/x', 'x', '/x', '')
19383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.checkShift('/','', None, '/', '')
19483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.checkShift('/a','/x/y', 'x', '/a/x', '/y')
19583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.checkShift('/a','/x/',  'x', '/a/x', '/')
19683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
19783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def testNormalizedShifts(self):
19883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.checkShift('/a/b', '/../y', '..', '/a', '/y')
19983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.checkShift('', '/../y', '..', '', '/y')
20083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.checkShift('/a/b', '//y', 'y', '/a/b/y', '')
20183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.checkShift('/a/b', '//y/', 'y', '/a/b/y', '/')
20283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.checkShift('/a/b', '/./y', 'y', '/a/b/y', '')
20383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.checkShift('/a/b', '/./y/', 'y', '/a/b/y', '/')
20483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.checkShift('/a/b', '///./..//y/.//', '..', '/a', '/y/')
20583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.checkShift('/a/b', '///', '', '/a/b/', '')
20683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.checkShift('/a/b', '/.//', '', '/a/b/', '')
20783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.checkShift('/a/b', '/x//', 'x', '/a/b/x', '/')
20883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.checkShift('/a/b', '/.', None, '/a/b', '')
20983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
21083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def testDefaults(self):
21183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        for key, value in [
21283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            ('SERVER_NAME','127.0.0.1'),
21383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            ('SERVER_PORT', '80'),
21483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            ('SERVER_PROTOCOL','HTTP/1.0'),
21583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            ('HTTP_HOST','127.0.0.1'),
21683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            ('REQUEST_METHOD','GET'),
21783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            ('SCRIPT_NAME',''),
21883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            ('PATH_INFO','/'),
21983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            ('wsgi.version', (1,0)),
22083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            ('wsgi.run_once', 0),
22183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            ('wsgi.multithread', 0),
22283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            ('wsgi.multiprocess', 0),
22383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            ('wsgi.input', StringIO("")),
22483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            ('wsgi.errors', StringIO()),
22583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            ('wsgi.url_scheme','http'),
22683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        ]:
22783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.checkDefault(key,value)
22883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
22983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def testCrossDefaults(self):
23083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.checkCrossDefault('HTTP_HOST',"foo.bar",SERVER_NAME="foo.bar")
23183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.checkCrossDefault('wsgi.url_scheme',"https",HTTPS="on")
23283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.checkCrossDefault('wsgi.url_scheme',"https",HTTPS="1")
23383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.checkCrossDefault('wsgi.url_scheme',"https",HTTPS="yes")
23483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.checkCrossDefault('wsgi.url_scheme',"http",HTTPS="foo")
23583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.checkCrossDefault('SERVER_PORT',"80",HTTPS="foo")
23683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.checkCrossDefault('SERVER_PORT',"443",HTTPS="on")
23783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
23883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def testGuessScheme(self):
23983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(util.guess_scheme({}), "http")
24083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(util.guess_scheme({'HTTPS':"foo"}), "http")
24183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(util.guess_scheme({'HTTPS':"on"}), "https")
24283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(util.guess_scheme({'HTTPS':"yes"}), "https")
24383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(util.guess_scheme({'HTTPS':"1"}), "https")
24483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
24583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def testAppURIs(self):
24683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.checkAppURI("http://127.0.0.1/")
24783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.checkAppURI("http://127.0.0.1/spam", SCRIPT_NAME="/spam")
24883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.checkAppURI("http://spam.example.com:2071/",
24983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            HTTP_HOST="spam.example.com:2071", SERVER_PORT="2071")
25083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.checkAppURI("http://spam.example.com/",
25183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            SERVER_NAME="spam.example.com")
25283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.checkAppURI("http://127.0.0.1/",
25383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            HTTP_HOST="127.0.0.1", SERVER_NAME="spam.example.com")
25483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.checkAppURI("https://127.0.0.1/", HTTPS="on")
25583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.checkAppURI("http://127.0.0.1:8000/", SERVER_PORT="8000",
25683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            HTTP_HOST=None)
25783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
25883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def testReqURIs(self):
25983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.checkReqURI("http://127.0.0.1/")
26083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.checkReqURI("http://127.0.0.1/spam", SCRIPT_NAME="/spam")
26183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.checkReqURI("http://127.0.0.1/spammity/spam",
26283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            SCRIPT_NAME="/spammity", PATH_INFO="/spam")
26383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.checkReqURI("http://127.0.0.1/spammity/spam;ham",
26483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            SCRIPT_NAME="/spammity", PATH_INFO="/spam;ham")
26583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.checkReqURI("http://127.0.0.1/spammity/spam;cookie=1234,5678",
26683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            SCRIPT_NAME="/spammity", PATH_INFO="/spam;cookie=1234,5678")
26783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.checkReqURI("http://127.0.0.1/spammity/spam?say=ni",
26883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            SCRIPT_NAME="/spammity", PATH_INFO="/spam",QUERY_STRING="say=ni")
26983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.checkReqURI("http://127.0.0.1/spammity/spam", 0,
27083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            SCRIPT_NAME="/spammity", PATH_INFO="/spam",QUERY_STRING="say=ni")
27183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
27283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def testFileWrapper(self):
27383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.checkFW("xyz"*50, 120, ["xyz"*40,"xyz"*10])
27483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
27583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def testHopByHop(self):
27683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        for hop in (
27783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            "Connection Keep-Alive Proxy-Authenticate Proxy-Authorization "
27883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            "TE Trailers Transfer-Encoding Upgrade"
27983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        ).split():
28083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            for alt in hop, hop.title(), hop.upper(), hop.lower():
28183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                self.assertTrue(util.is_hop_by_hop(alt))
28283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
28383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # Not comprehensive, just a few random header names
28483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        for hop in (
28583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            "Accept Cache-Control Date Pragma Trailer Via Warning"
28683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        ).split():
28783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            for alt in hop, hop.title(), hop.upper(), hop.lower():
28883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                self.assertFalse(util.is_hop_by_hop(alt))
28983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
29083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass HeaderTests(TestCase):
29183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
29283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def testMappingInterface(self):
29383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        test = [('x','y')]
29483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(len(Headers([])),0)
29583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(len(Headers(test[:])),1)
29683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(Headers(test[:]).keys(), ['x'])
29783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(Headers(test[:]).values(), ['y'])
29883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(Headers(test[:]).items(), test)
29983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertFalse(Headers(test).items() is test)  # must be copy!
30083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
30183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        h=Headers([])
30283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        del h['foo']   # should not raise an error
30383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
30483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        h['Foo'] = 'bar'
30583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        for m in h.has_key, h.__contains__, h.get, h.get_all, h.__getitem__:
30683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.assertTrue(m('foo'))
30783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.assertTrue(m('Foo'))
30883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.assertTrue(m('FOO'))
30983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.assertFalse(m('bar'))
31083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
31183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(h['foo'],'bar')
31283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        h['foo'] = 'baz'
31383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(h['FOO'],'baz')
31483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(h.get_all('foo'),['baz'])
31583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
31683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(h.get("foo","whee"), "baz")
31783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(h.get("zoo","whee"), "whee")
31883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(h.setdefault("foo","whee"), "baz")
31983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(h.setdefault("zoo","whee"), "whee")
32083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(h["foo"],"baz")
32183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(h["zoo"],"whee")
32283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
32383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def testRequireList(self):
32483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertRaises(TypeError, Headers, "foo")
32583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
32683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
32783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def testExtras(self):
32883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        h = Headers([])
32983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(str(h),'\r\n')
33083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
33183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        h.add_header('foo','bar',baz="spam")
33283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(h['foo'], 'bar; baz="spam"')
33383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(str(h),'foo: bar; baz="spam"\r\n\r\n')
33483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
33583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        h.add_header('Foo','bar',cheese=None)
33683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(h.get_all('foo'),
33783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            ['bar; baz="spam"', 'bar; cheese'])
33883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
33983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(str(h),
34083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            'foo: bar; baz="spam"\r\n'
34183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            'Foo: bar; cheese\r\n'
34283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            '\r\n'
34383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        )
34483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
34583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
34683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass ErrorHandler(BaseCGIHandler):
34783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    """Simple handler subclass for testing BaseHandler"""
34883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
34983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    # BaseHandler records the OS environment at import time, but envvars
35083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    # might have been changed later by other tests, which trips up
35183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    # HandlerTests.testEnviron().
35283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    os_environ = dict(os.environ.items())
35383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
35483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __init__(self,**kw):
35583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        setup_testing_defaults(kw)
35683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        BaseCGIHandler.__init__(
35783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self, StringIO(''), StringIO(), StringIO(), kw,
35883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            multithread=True, multiprocess=True
35983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        )
36083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
36183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass TestHandler(ErrorHandler):
36283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    """Simple handler subclass for testing BaseHandler, w/error passthru"""
36383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
36483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def handle_error(self):
36583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        raise   # for testing, we want to see what's happening
36683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
36783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
36883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass HandlerTests(TestCase):
36983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
37083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def checkEnvironAttrs(self, handler):
37183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        env = handler.environ
37283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        for attr in [
37383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            'version','multithread','multiprocess','run_once','file_wrapper'
37483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        ]:
37583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if attr=='file_wrapper' and handler.wsgi_file_wrapper is None:
37683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                continue
37783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.assertEqual(getattr(handler,'wsgi_'+attr),env['wsgi.'+attr])
37883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
37983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def checkOSEnviron(self,handler):
38083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        empty = {}; setup_testing_defaults(empty)
38183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        env = handler.environ
38283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        from os import environ
38383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        for k,v in environ.items():
38483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if k not in empty:
38583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                self.assertEqual(env[k],v)
38683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        for k,v in empty.items():
38783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.assertIn(k, env)
38883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
38983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def testEnviron(self):
39083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        h = TestHandler(X="Y")
39183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        h.setup_environ()
39283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.checkEnvironAttrs(h)
39383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.checkOSEnviron(h)
39483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(h.environ["X"],"Y")
39583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
39683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def testCGIEnviron(self):
39783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        h = BaseCGIHandler(None,None,None,{})
39883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        h.setup_environ()
39983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        for key in 'wsgi.url_scheme', 'wsgi.input', 'wsgi.errors':
40083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.assertIn(key, h.environ)
40183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
40283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def testScheme(self):
40383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        h=TestHandler(HTTPS="on"); h.setup_environ()
40483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(h.environ['wsgi.url_scheme'],'https')
40583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        h=TestHandler(); h.setup_environ()
40683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(h.environ['wsgi.url_scheme'],'http')
40783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
40883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def testAbstractMethods(self):
40983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        h = BaseHandler()
41083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        for name in [
41183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            '_flush','get_stdin','get_stderr','add_cgi_vars'
41283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        ]:
41383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.assertRaises(NotImplementedError, getattr(h,name))
41483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertRaises(NotImplementedError, h._write, "test")
41583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
41683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def testContentLength(self):
41783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # Demo one reason iteration is better than write()...  ;)
41883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
41983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        def trivial_app1(e,s):
42083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            s('200 OK',[])
42183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return [e['wsgi.url_scheme']]
42283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
42383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        def trivial_app2(e,s):
42483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            s('200 OK',[])(e['wsgi.url_scheme'])
42583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return []
42683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
42783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        def trivial_app4(e,s):
42883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            # Simulate a response to a HEAD request
42983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            s('200 OK',[('Content-Length', '12345')])
43083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return []
43183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
43283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        h = TestHandler()
43383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        h.run(trivial_app1)
43483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(h.stdout.getvalue(),
43583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            "Status: 200 OK\r\n"
43683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            "Content-Length: 4\r\n"
43783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            "\r\n"
43883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            "http")
43983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
44083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        h = TestHandler()
44183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        h.run(trivial_app2)
44283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(h.stdout.getvalue(),
44383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            "Status: 200 OK\r\n"
44483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            "\r\n"
44583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            "http")
44683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
44783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
44883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        h = TestHandler()
44983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        h.run(trivial_app4)
45083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(h.stdout.getvalue(),
45183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            b'Status: 200 OK\r\n'
45283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            b'Content-Length: 12345\r\n'
45383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            b'\r\n')
45483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
45583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def testBasicErrorOutput(self):
45683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
45783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        def non_error_app(e,s):
45883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            s('200 OK',[])
45983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return []
46083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
46183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        def error_app(e,s):
46283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            raise AssertionError("This should be caught by handler")
46383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
46483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        h = ErrorHandler()
46583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        h.run(non_error_app)
46683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(h.stdout.getvalue(),
46783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            "Status: 200 OK\r\n"
46883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            "Content-Length: 0\r\n"
46983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            "\r\n")
47083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(h.stderr.getvalue(),"")
47183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
47283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        h = ErrorHandler()
47383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        h.run(error_app)
47483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(h.stdout.getvalue(),
47583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            "Status: %s\r\n"
47683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            "Content-Type: text/plain\r\n"
47783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            "Content-Length: %d\r\n"
47883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            "\r\n%s" % (h.error_status,len(h.error_body),h.error_body))
47983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
48083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertNotEqual(h.stderr.getvalue().find("AssertionError"), -1)
48183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
48283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def testErrorAfterOutput(self):
48383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        MSG = "Some output has been sent"
48483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        def error_app(e,s):
48583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            s("200 OK",[])(MSG)
48683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            raise AssertionError("This should be caught by handler")
48783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
48883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        h = ErrorHandler()
48983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        h.run(error_app)
49083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(h.stdout.getvalue(),
49183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            "Status: 200 OK\r\n"
49283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            "\r\n"+MSG)
49383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertNotEqual(h.stderr.getvalue().find("AssertionError"), -1)
49483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
49583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def testHeaderFormats(self):
49683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
49783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        def non_error_app(e,s):
49883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            s('200 OK',[])
49983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return []
50083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
50183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        stdpat = (
50283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            r"HTTP/%s 200 OK\r\n"
50383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            r"Date: \w{3}, [ 0123]\d \w{3} \d{4} \d\d:\d\d:\d\d GMT\r\n"
50483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            r"%s" r"Content-Length: 0\r\n" r"\r\n"
50583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        )
50683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        shortpat = (
50783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            "Status: 200 OK\r\n" "Content-Length: 0\r\n" "\r\n"
50883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        )
50983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
51083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        for ssw in "FooBar/1.0", None:
51183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            sw = ssw and "Server: %s\r\n" % ssw or ""
51283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
51383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            for version in "1.0", "1.1":
51483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                for proto in "HTTP/0.9", "HTTP/1.0", "HTTP/1.1":
51583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
51683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    h = TestHandler(SERVER_PROTOCOL=proto)
51783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    h.origin_server = False
51883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    h.http_version = version
51983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    h.server_software = ssw
52083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    h.run(non_error_app)
52183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    self.assertEqual(shortpat,h.stdout.getvalue())
52283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
52383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    h = TestHandler(SERVER_PROTOCOL=proto)
52483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    h.origin_server = True
52583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    h.http_version = version
52683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    h.server_software = ssw
52783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    h.run(non_error_app)
52883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    if proto=="HTTP/0.9":
52983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                        self.assertEqual(h.stdout.getvalue(),"")
53083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    else:
53183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                        self.assertTrue(
53283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                            re.match(stdpat%(version,sw), h.stdout.getvalue()),
53383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                            (stdpat%(version,sw), h.stdout.getvalue())
53483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                        )
53583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
53683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def testCloseOnError(self):
53783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        side_effects = {'close_called': False}
53883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        MSG = b"Some output has been sent"
53983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        def error_app(e,s):
54083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            s("200 OK",[])(MSG)
54183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            class CrashyIterable(object):
54283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                def __iter__(self):
54383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    while True:
54483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                        yield b'blah'
54583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                        raise AssertionError("This should be caught by handler")
54683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
54783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                def close(self):
54883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    side_effects['close_called'] = True
54983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return CrashyIterable()
55083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
55183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        h = ErrorHandler()
55283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        h.run(error_app)
55383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.assertEqual(side_effects['close_called'], True)
55483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
55583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
55683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef test_main():
55783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    test_support.run_unittest(__name__)
55883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
55983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehif __name__ == "__main__":
56083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    test_main()
561