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