python-2.5.2/win32/Lib/test/test_wsgiref.py
changeset 0 ae805ac0140d
equal deleted inserted replaced
-1:000000000000 0:ae805ac0140d
       
     1 from __future__ import nested_scopes    # Backward compat for 2.1
       
     2 from unittest import TestSuite, TestCase, makeSuite
       
     3 from wsgiref.util import setup_testing_defaults
       
     4 from wsgiref.headers import Headers
       
     5 from wsgiref.handlers import BaseHandler, BaseCGIHandler
       
     6 from wsgiref import util
       
     7 from wsgiref.validate import validator
       
     8 from wsgiref.simple_server import WSGIServer, WSGIRequestHandler, demo_app
       
     9 from wsgiref.simple_server import make_server
       
    10 from StringIO import StringIO
       
    11 from SocketServer import BaseServer
       
    12 import re, sys
       
    13 
       
    14 
       
    15 class MockServer(WSGIServer):
       
    16     """Non-socket HTTP server"""
       
    17 
       
    18     def __init__(self, server_address, RequestHandlerClass):
       
    19         BaseServer.__init__(self, server_address, RequestHandlerClass)
       
    20         self.server_bind()
       
    21 
       
    22     def server_bind(self):
       
    23         host, port = self.server_address
       
    24         self.server_name = host
       
    25         self.server_port = port
       
    26         self.setup_environ()
       
    27 
       
    28 
       
    29 class MockHandler(WSGIRequestHandler):
       
    30     """Non-socket HTTP handler"""
       
    31     def setup(self):
       
    32         self.connection = self.request
       
    33         self.rfile, self.wfile = self.connection
       
    34 
       
    35     def finish(self):
       
    36         pass
       
    37 
       
    38 
       
    39 
       
    40 
       
    41 
       
    42 def hello_app(environ,start_response):
       
    43     start_response("200 OK", [
       
    44         ('Content-Type','text/plain'),
       
    45         ('Date','Mon, 05 Jun 2006 18:49:54 GMT')
       
    46     ])
       
    47     return ["Hello, world!"]
       
    48 
       
    49 def run_amock(app=hello_app, data="GET / HTTP/1.0\n\n"):
       
    50     server = make_server("", 80, app, MockServer, MockHandler)
       
    51     inp, out, err, olderr = StringIO(data), StringIO(), StringIO(), sys.stderr
       
    52     sys.stderr = err
       
    53 
       
    54     try:
       
    55         server.finish_request((inp,out), ("127.0.0.1",8888))
       
    56     finally:
       
    57         sys.stderr = olderr
       
    58 
       
    59     return out.getvalue(), err.getvalue()
       
    60 
       
    61 
       
    62 
       
    63 
       
    64 
       
    65 
       
    66 
       
    67 
       
    68 
       
    69 
       
    70 
       
    71 
       
    72 
       
    73 
       
    74 
       
    75 
       
    76 
       
    77 
       
    78 
       
    79 
       
    80 
       
    81 
       
    82 
       
    83 def compare_generic_iter(make_it,match):
       
    84     """Utility to compare a generic 2.1/2.2+ iterator with an iterable
       
    85 
       
    86     If running under Python 2.2+, this tests the iterator using iter()/next(),
       
    87     as well as __getitem__.  'make_it' must be a function returning a fresh
       
    88     iterator to be tested (since this may test the iterator twice)."""
       
    89 
       
    90     it = make_it()
       
    91     n = 0
       
    92     for item in match:
       
    93         if not it[n]==item: raise AssertionError
       
    94         n+=1
       
    95     try:
       
    96         it[n]
       
    97     except IndexError:
       
    98         pass
       
    99     else:
       
   100         raise AssertionError("Too many items from __getitem__",it)
       
   101 
       
   102     try:
       
   103         iter, StopIteration
       
   104     except NameError:
       
   105         pass
       
   106     else:
       
   107         # Only test iter mode under 2.2+
       
   108         it = make_it()
       
   109         if not iter(it) is it: raise AssertionError
       
   110         for item in match:
       
   111             if not it.next()==item: raise AssertionError
       
   112         try:
       
   113             it.next()
       
   114         except StopIteration:
       
   115             pass
       
   116         else:
       
   117             raise AssertionError("Too many items from .next()",it)
       
   118 
       
   119 
       
   120 
       
   121 
       
   122 
       
   123 
       
   124 class IntegrationTests(TestCase):
       
   125 
       
   126     def check_hello(self, out, has_length=True):
       
   127         self.assertEqual(out,
       
   128             "HTTP/1.0 200 OK\r\n"
       
   129             "Server: WSGIServer/0.1 Python/"+sys.version.split()[0]+"\r\n"
       
   130             "Content-Type: text/plain\r\n"
       
   131             "Date: Mon, 05 Jun 2006 18:49:54 GMT\r\n" +
       
   132             (has_length and  "Content-Length: 13\r\n" or "") +
       
   133             "\r\n"
       
   134             "Hello, world!"
       
   135         )
       
   136 
       
   137     def test_plain_hello(self):
       
   138         out, err = run_amock()
       
   139         self.check_hello(out)
       
   140 
       
   141     def test_validated_hello(self):
       
   142         out, err = run_amock(validator(hello_app))
       
   143         # the middleware doesn't support len(), so content-length isn't there
       
   144         self.check_hello(out, has_length=False)
       
   145 
       
   146     def test_simple_validation_error(self):
       
   147         def bad_app(environ,start_response):
       
   148             start_response("200 OK", ('Content-Type','text/plain'))
       
   149             return ["Hello, world!"]
       
   150         out, err = run_amock(validator(bad_app))
       
   151         self.failUnless(out.endswith(
       
   152             "A server error occurred.  Please contact the administrator."
       
   153         ))
       
   154         self.assertEqual(
       
   155             err.splitlines()[-2],
       
   156             "AssertionError: Headers (('Content-Type', 'text/plain')) must"
       
   157             " be of type list: <type 'tuple'>"
       
   158         )
       
   159 
       
   160 
       
   161 
       
   162 
       
   163 
       
   164 
       
   165 class UtilityTests(TestCase):
       
   166 
       
   167     def checkShift(self,sn_in,pi_in,part,sn_out,pi_out):
       
   168         env = {'SCRIPT_NAME':sn_in,'PATH_INFO':pi_in}
       
   169         util.setup_testing_defaults(env)
       
   170         self.assertEqual(util.shift_path_info(env),part)
       
   171         self.assertEqual(env['PATH_INFO'],pi_out)
       
   172         self.assertEqual(env['SCRIPT_NAME'],sn_out)
       
   173         return env
       
   174 
       
   175     def checkDefault(self, key, value, alt=None):
       
   176         # Check defaulting when empty
       
   177         env = {}
       
   178         util.setup_testing_defaults(env)
       
   179         if isinstance(value,StringIO):
       
   180             self.failUnless(isinstance(env[key],StringIO))
       
   181         else:
       
   182             self.assertEqual(env[key],value)
       
   183 
       
   184         # Check existing value
       
   185         env = {key:alt}
       
   186         util.setup_testing_defaults(env)
       
   187         self.failUnless(env[key] is alt)
       
   188 
       
   189     def checkCrossDefault(self,key,value,**kw):
       
   190         util.setup_testing_defaults(kw)
       
   191         self.assertEqual(kw[key],value)
       
   192 
       
   193     def checkAppURI(self,uri,**kw):
       
   194         util.setup_testing_defaults(kw)
       
   195         self.assertEqual(util.application_uri(kw),uri)
       
   196 
       
   197     def checkReqURI(self,uri,query=1,**kw):
       
   198         util.setup_testing_defaults(kw)
       
   199         self.assertEqual(util.request_uri(kw,query),uri)
       
   200 
       
   201 
       
   202 
       
   203 
       
   204 
       
   205 
       
   206     def checkFW(self,text,size,match):
       
   207 
       
   208         def make_it(text=text,size=size):
       
   209             return util.FileWrapper(StringIO(text),size)
       
   210 
       
   211         compare_generic_iter(make_it,match)
       
   212 
       
   213         it = make_it()
       
   214         self.failIf(it.filelike.closed)
       
   215 
       
   216         for item in it:
       
   217             pass
       
   218 
       
   219         self.failIf(it.filelike.closed)
       
   220 
       
   221         it.close()
       
   222         self.failUnless(it.filelike.closed)
       
   223 
       
   224 
       
   225     def testSimpleShifts(self):
       
   226         self.checkShift('','/', '', '/', '')
       
   227         self.checkShift('','/x', 'x', '/x', '')
       
   228         self.checkShift('/','', None, '/', '')
       
   229         self.checkShift('/a','/x/y', 'x', '/a/x', '/y')
       
   230         self.checkShift('/a','/x/',  'x', '/a/x', '/')
       
   231 
       
   232 
       
   233     def testNormalizedShifts(self):
       
   234         self.checkShift('/a/b', '/../y', '..', '/a', '/y')
       
   235         self.checkShift('', '/../y', '..', '', '/y')
       
   236         self.checkShift('/a/b', '//y', 'y', '/a/b/y', '')
       
   237         self.checkShift('/a/b', '//y/', 'y', '/a/b/y', '/')
       
   238         self.checkShift('/a/b', '/./y', 'y', '/a/b/y', '')
       
   239         self.checkShift('/a/b', '/./y/', 'y', '/a/b/y', '/')
       
   240         self.checkShift('/a/b', '///./..//y/.//', '..', '/a', '/y/')
       
   241         self.checkShift('/a/b', '///', '', '/a/b/', '')
       
   242         self.checkShift('/a/b', '/.//', '', '/a/b/', '')
       
   243         self.checkShift('/a/b', '/x//', 'x', '/a/b/x', '/')
       
   244         self.checkShift('/a/b', '/.', None, '/a/b', '')
       
   245 
       
   246 
       
   247     def testDefaults(self):
       
   248         for key, value in [
       
   249             ('SERVER_NAME','127.0.0.1'),
       
   250             ('SERVER_PORT', '80'),
       
   251             ('SERVER_PROTOCOL','HTTP/1.0'),
       
   252             ('HTTP_HOST','127.0.0.1'),
       
   253             ('REQUEST_METHOD','GET'),
       
   254             ('SCRIPT_NAME',''),
       
   255             ('PATH_INFO','/'),
       
   256             ('wsgi.version', (1,0)),
       
   257             ('wsgi.run_once', 0),
       
   258             ('wsgi.multithread', 0),
       
   259             ('wsgi.multiprocess', 0),
       
   260             ('wsgi.input', StringIO("")),
       
   261             ('wsgi.errors', StringIO()),
       
   262             ('wsgi.url_scheme','http'),
       
   263         ]:
       
   264             self.checkDefault(key,value)
       
   265 
       
   266 
       
   267     def testCrossDefaults(self):
       
   268         self.checkCrossDefault('HTTP_HOST',"foo.bar",SERVER_NAME="foo.bar")
       
   269         self.checkCrossDefault('wsgi.url_scheme',"https",HTTPS="on")
       
   270         self.checkCrossDefault('wsgi.url_scheme',"https",HTTPS="1")
       
   271         self.checkCrossDefault('wsgi.url_scheme',"https",HTTPS="yes")
       
   272         self.checkCrossDefault('wsgi.url_scheme',"http",HTTPS="foo")
       
   273         self.checkCrossDefault('SERVER_PORT',"80",HTTPS="foo")
       
   274         self.checkCrossDefault('SERVER_PORT',"443",HTTPS="on")
       
   275 
       
   276 
       
   277     def testGuessScheme(self):
       
   278         self.assertEqual(util.guess_scheme({}), "http")
       
   279         self.assertEqual(util.guess_scheme({'HTTPS':"foo"}), "http")
       
   280         self.assertEqual(util.guess_scheme({'HTTPS':"on"}), "https")
       
   281         self.assertEqual(util.guess_scheme({'HTTPS':"yes"}), "https")
       
   282         self.assertEqual(util.guess_scheme({'HTTPS':"1"}), "https")
       
   283 
       
   284 
       
   285 
       
   286 
       
   287 
       
   288     def testAppURIs(self):
       
   289         self.checkAppURI("http://127.0.0.1/")
       
   290         self.checkAppURI("http://127.0.0.1/spam", SCRIPT_NAME="/spam")
       
   291         self.checkAppURI("http://spam.example.com:2071/",
       
   292             HTTP_HOST="spam.example.com:2071", SERVER_PORT="2071")
       
   293         self.checkAppURI("http://spam.example.com/",
       
   294             SERVER_NAME="spam.example.com")
       
   295         self.checkAppURI("http://127.0.0.1/",
       
   296             HTTP_HOST="127.0.0.1", SERVER_NAME="spam.example.com")
       
   297         self.checkAppURI("https://127.0.0.1/", HTTPS="on")
       
   298         self.checkAppURI("http://127.0.0.1:8000/", SERVER_PORT="8000",
       
   299             HTTP_HOST=None)
       
   300 
       
   301     def testReqURIs(self):
       
   302         self.checkReqURI("http://127.0.0.1/")
       
   303         self.checkReqURI("http://127.0.0.1/spam", SCRIPT_NAME="/spam")
       
   304         self.checkReqURI("http://127.0.0.1/spammity/spam",
       
   305             SCRIPT_NAME="/spammity", PATH_INFO="/spam")
       
   306         self.checkReqURI("http://127.0.0.1/spammity/spam?say=ni",
       
   307             SCRIPT_NAME="/spammity", PATH_INFO="/spam",QUERY_STRING="say=ni")
       
   308         self.checkReqURI("http://127.0.0.1/spammity/spam", 0,
       
   309             SCRIPT_NAME="/spammity", PATH_INFO="/spam",QUERY_STRING="say=ni")
       
   310 
       
   311     def testFileWrapper(self):
       
   312         self.checkFW("xyz"*50, 120, ["xyz"*40,"xyz"*10])
       
   313 
       
   314     def testHopByHop(self):
       
   315         for hop in (
       
   316             "Connection Keep-Alive Proxy-Authenticate Proxy-Authorization "
       
   317             "TE Trailers Transfer-Encoding Upgrade"
       
   318         ).split():
       
   319             for alt in hop, hop.title(), hop.upper(), hop.lower():
       
   320                 self.failUnless(util.is_hop_by_hop(alt))
       
   321 
       
   322         # Not comprehensive, just a few random header names
       
   323         for hop in (
       
   324             "Accept Cache-Control Date Pragma Trailer Via Warning"
       
   325         ).split():
       
   326             for alt in hop, hop.title(), hop.upper(), hop.lower():
       
   327                 self.failIf(util.is_hop_by_hop(alt))
       
   328 
       
   329 class HeaderTests(TestCase):
       
   330 
       
   331     def testMappingInterface(self):
       
   332         test = [('x','y')]
       
   333         self.assertEqual(len(Headers([])),0)
       
   334         self.assertEqual(len(Headers(test[:])),1)
       
   335         self.assertEqual(Headers(test[:]).keys(), ['x'])
       
   336         self.assertEqual(Headers(test[:]).values(), ['y'])
       
   337         self.assertEqual(Headers(test[:]).items(), test)
       
   338         self.failIf(Headers(test).items() is test)  # must be copy!
       
   339 
       
   340         h=Headers([])
       
   341         del h['foo']   # should not raise an error
       
   342 
       
   343         h['Foo'] = 'bar'
       
   344         for m in h.has_key, h.__contains__, h.get, h.get_all, h.__getitem__:
       
   345             self.failUnless(m('foo'))
       
   346             self.failUnless(m('Foo'))
       
   347             self.failUnless(m('FOO'))
       
   348             self.failIf(m('bar'))
       
   349 
       
   350         self.assertEqual(h['foo'],'bar')
       
   351         h['foo'] = 'baz'
       
   352         self.assertEqual(h['FOO'],'baz')
       
   353         self.assertEqual(h.get_all('foo'),['baz'])
       
   354 
       
   355         self.assertEqual(h.get("foo","whee"), "baz")
       
   356         self.assertEqual(h.get("zoo","whee"), "whee")
       
   357         self.assertEqual(h.setdefault("foo","whee"), "baz")
       
   358         self.assertEqual(h.setdefault("zoo","whee"), "whee")
       
   359         self.assertEqual(h["foo"],"baz")
       
   360         self.assertEqual(h["zoo"],"whee")
       
   361 
       
   362     def testRequireList(self):
       
   363         self.assertRaises(TypeError, Headers, "foo")
       
   364 
       
   365 
       
   366     def testExtras(self):
       
   367         h = Headers([])
       
   368         self.assertEqual(str(h),'\r\n')
       
   369 
       
   370         h.add_header('foo','bar',baz="spam")
       
   371         self.assertEqual(h['foo'], 'bar; baz="spam"')
       
   372         self.assertEqual(str(h),'foo: bar; baz="spam"\r\n\r\n')
       
   373 
       
   374         h.add_header('Foo','bar',cheese=None)
       
   375         self.assertEqual(h.get_all('foo'),
       
   376             ['bar; baz="spam"', 'bar; cheese'])
       
   377 
       
   378         self.assertEqual(str(h),
       
   379             'foo: bar; baz="spam"\r\n'
       
   380             'Foo: bar; cheese\r\n'
       
   381             '\r\n'
       
   382         )
       
   383 
       
   384 
       
   385 class ErrorHandler(BaseCGIHandler):
       
   386     """Simple handler subclass for testing BaseHandler"""
       
   387 
       
   388     def __init__(self,**kw):
       
   389         setup_testing_defaults(kw)
       
   390         BaseCGIHandler.__init__(
       
   391             self, StringIO(''), StringIO(), StringIO(), kw,
       
   392             multithread=True, multiprocess=True
       
   393         )
       
   394 
       
   395 class TestHandler(ErrorHandler):
       
   396     """Simple handler subclass for testing BaseHandler, w/error passthru"""
       
   397 
       
   398     def handle_error(self):
       
   399         raise   # for testing, we want to see what's happening
       
   400 
       
   401 
       
   402 
       
   403 
       
   404 
       
   405 
       
   406 
       
   407 
       
   408 
       
   409 
       
   410 
       
   411 class HandlerTests(TestCase):
       
   412 
       
   413     def checkEnvironAttrs(self, handler):
       
   414         env = handler.environ
       
   415         for attr in [
       
   416             'version','multithread','multiprocess','run_once','file_wrapper'
       
   417         ]:
       
   418             if attr=='file_wrapper' and handler.wsgi_file_wrapper is None:
       
   419                 continue
       
   420             self.assertEqual(getattr(handler,'wsgi_'+attr),env['wsgi.'+attr])
       
   421 
       
   422     def checkOSEnviron(self,handler):
       
   423         empty = {}; setup_testing_defaults(empty)
       
   424         env = handler.environ
       
   425         from os import environ
       
   426         for k,v in environ.items():
       
   427             if not empty.has_key(k):
       
   428                 self.assertEqual(env[k],v)
       
   429         for k,v in empty.items():
       
   430             self.failUnless(env.has_key(k))
       
   431 
       
   432     def testEnviron(self):
       
   433         h = TestHandler(X="Y")
       
   434         h.setup_environ()
       
   435         self.checkEnvironAttrs(h)
       
   436         self.checkOSEnviron(h)
       
   437         self.assertEqual(h.environ["X"],"Y")
       
   438 
       
   439     def testCGIEnviron(self):
       
   440         h = BaseCGIHandler(None,None,None,{})
       
   441         h.setup_environ()
       
   442         for key in 'wsgi.url_scheme', 'wsgi.input', 'wsgi.errors':
       
   443             self.assert_(h.environ.has_key(key))
       
   444 
       
   445     def testScheme(self):
       
   446         h=TestHandler(HTTPS="on"); h.setup_environ()
       
   447         self.assertEqual(h.environ['wsgi.url_scheme'],'https')
       
   448         h=TestHandler(); h.setup_environ()
       
   449         self.assertEqual(h.environ['wsgi.url_scheme'],'http')
       
   450 
       
   451 
       
   452     def testAbstractMethods(self):
       
   453         h = BaseHandler()
       
   454         for name in [
       
   455             '_flush','get_stdin','get_stderr','add_cgi_vars'
       
   456         ]:
       
   457             self.assertRaises(NotImplementedError, getattr(h,name))
       
   458         self.assertRaises(NotImplementedError, h._write, "test")
       
   459 
       
   460 
       
   461     def testContentLength(self):
       
   462         # Demo one reason iteration is better than write()...  ;)
       
   463 
       
   464         def trivial_app1(e,s):
       
   465             s('200 OK',[])
       
   466             return [e['wsgi.url_scheme']]
       
   467 
       
   468         def trivial_app2(e,s):
       
   469             s('200 OK',[])(e['wsgi.url_scheme'])
       
   470             return []
       
   471 
       
   472         h = TestHandler()
       
   473         h.run(trivial_app1)
       
   474         self.assertEqual(h.stdout.getvalue(),
       
   475             "Status: 200 OK\r\n"
       
   476             "Content-Length: 4\r\n"
       
   477             "\r\n"
       
   478             "http")
       
   479 
       
   480         h = TestHandler()
       
   481         h.run(trivial_app2)
       
   482         self.assertEqual(h.stdout.getvalue(),
       
   483             "Status: 200 OK\r\n"
       
   484             "\r\n"
       
   485             "http")
       
   486 
       
   487 
       
   488 
       
   489 
       
   490 
       
   491 
       
   492 
       
   493     def testBasicErrorOutput(self):
       
   494 
       
   495         def non_error_app(e,s):
       
   496             s('200 OK',[])
       
   497             return []
       
   498 
       
   499         def error_app(e,s):
       
   500             raise AssertionError("This should be caught by handler")
       
   501 
       
   502         h = ErrorHandler()
       
   503         h.run(non_error_app)
       
   504         self.assertEqual(h.stdout.getvalue(),
       
   505             "Status: 200 OK\r\n"
       
   506             "Content-Length: 0\r\n"
       
   507             "\r\n")
       
   508         self.assertEqual(h.stderr.getvalue(),"")
       
   509 
       
   510         h = ErrorHandler()
       
   511         h.run(error_app)
       
   512         self.assertEqual(h.stdout.getvalue(),
       
   513             "Status: %s\r\n"
       
   514             "Content-Type: text/plain\r\n"
       
   515             "Content-Length: %d\r\n"
       
   516             "\r\n%s" % (h.error_status,len(h.error_body),h.error_body))
       
   517 
       
   518         self.failUnless(h.stderr.getvalue().find("AssertionError")<>-1)
       
   519 
       
   520     def testErrorAfterOutput(self):
       
   521         MSG = "Some output has been sent"
       
   522         def error_app(e,s):
       
   523             s("200 OK",[])(MSG)
       
   524             raise AssertionError("This should be caught by handler")
       
   525 
       
   526         h = ErrorHandler()
       
   527         h.run(error_app)
       
   528         self.assertEqual(h.stdout.getvalue(),
       
   529             "Status: 200 OK\r\n"
       
   530             "\r\n"+MSG)
       
   531         self.failUnless(h.stderr.getvalue().find("AssertionError")<>-1)
       
   532 
       
   533 
       
   534     def testHeaderFormats(self):
       
   535 
       
   536         def non_error_app(e,s):
       
   537             s('200 OK',[])
       
   538             return []
       
   539 
       
   540         stdpat = (
       
   541             r"HTTP/%s 200 OK\r\n"
       
   542             r"Date: \w{3}, [ 0123]\d \w{3} \d{4} \d\d:\d\d:\d\d GMT\r\n"
       
   543             r"%s" r"Content-Length: 0\r\n" r"\r\n"
       
   544         )
       
   545         shortpat = (
       
   546             "Status: 200 OK\r\n" "Content-Length: 0\r\n" "\r\n"
       
   547         )
       
   548 
       
   549         for ssw in "FooBar/1.0", None:
       
   550             sw = ssw and "Server: %s\r\n" % ssw or ""
       
   551 
       
   552             for version in "1.0", "1.1":
       
   553                 for proto in "HTTP/0.9", "HTTP/1.0", "HTTP/1.1":
       
   554 
       
   555                     h = TestHandler(SERVER_PROTOCOL=proto)
       
   556                     h.origin_server = False
       
   557                     h.http_version = version
       
   558                     h.server_software = ssw
       
   559                     h.run(non_error_app)
       
   560                     self.assertEqual(shortpat,h.stdout.getvalue())
       
   561 
       
   562                     h = TestHandler(SERVER_PROTOCOL=proto)
       
   563                     h.origin_server = True
       
   564                     h.http_version = version
       
   565                     h.server_software = ssw
       
   566                     h.run(non_error_app)
       
   567                     if proto=="HTTP/0.9":
       
   568                         self.assertEqual(h.stdout.getvalue(),"")
       
   569                     else:
       
   570                         self.failUnless(
       
   571                             re.match(stdpat%(version,sw), h.stdout.getvalue()),
       
   572                             (stdpat%(version,sw), h.stdout.getvalue())
       
   573                         )
       
   574 
       
   575 # This epilogue is needed for compatibility with the Python 2.5 regrtest module
       
   576 
       
   577 def test_main():
       
   578     import unittest
       
   579     from test.test_support import run_suite
       
   580     run_suite(
       
   581         unittest.defaultTestLoader.loadTestsFromModule(sys.modules[__name__])
       
   582     )
       
   583 
       
   584 if __name__ == "__main__":
       
   585     test_main()
       
   586 
       
   587 
       
   588 
       
   589 
       
   590 
       
   591 
       
   592 
       
   593 
       
   594 
       
   595 
       
   596 
       
   597 
       
   598 
       
   599 
       
   600 
       
   601 
       
   602 
       
   603 
       
   604 
       
   605 
       
   606 
       
   607 
       
   608 
       
   609 
       
   610 
       
   611 
       
   612 
       
   613 
       
   614 
       
   615 # the above lines intentionally left blank