Download Install Tutorial Docs FAQ Tools WikiLicense Team IRC Planet Involvement Shop Book

Changeset 1017

Show
Ignore:
Timestamp:
03/26/06 16:14:11
Author:
fumanchu
Message:

Initial fix for #498 (Test suite assumes same process for client and server). All test modules now wrap the server-side code in a "setup_server" function. New test\modpy module (with several tests failing).

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/cherrypy/test/helper.py

    r1014 r1017  
    55 
    66Usage: 
    7   Each individual test_*.py module imports this module (helper), 
    8   usually to make an instance of CPWebCase, and then call testmain(). 
    9    
    10   The CP test suite script (test.py) imports this module and calls 
    11   run_test_suite, possibly more than once. CP applications may also 
    12   import test.py (to use TestHarness), which then calls helper.py. 
     7    Each individual test_*.py module imports this module (helper), 
     8    usually to make an instance of CPWebCase, and then call testmain(). 
     9     
     10    The CP test suite script (test.py) imports this module and calls 
     11    run_test_suite, possibly more than once. CP applications may also 
     12    import test.py (to use TestHarness), which then calls helper.py. 
    1313""" 
    1414 
     
    1818# or vice-versa, unless you *really* know what you're doing. 
    1919 
    20 import os, os.path 
    2120import re 
    22 import socket 
    23 import StringIO 
    2421import sys 
    2522import thread 
    26 import threading 
    27 import time 
    28 import types 
    2923 
    3024import cherrypy 
    31 from cherrypy import _cpwsgi 
    3225from cherrypy.lib import httptools 
    3326import webtest 
    34  
    35 for _x in dir(cherrypy): 
    36     y = getattr(cherrypy, _x) 
    37     if isinstance(y, types.ClassType) and issubclass(y, cherrypy.Error): 
    38         webtest.ignored_exceptions.append(y) 
    39  
    40  
    41 def onerror(): 
    42     """Assign to _cp_on_error to enable webtest server-side debugging.""" 
    43     handled = webtest.server_error() 
    44     if not handled: 
    45         cherrypy._cputil._cp_on_error() 
    46  
    47  
    48 def error_middleware(environ, start_response): 
    49     started = [False] 
    50     def start(s, h, exc=None): 
    51         started[0] = True 
    52         start_response(s, h, exc) 
    53      
    54     try: 
    55         for chunk in _cpwsgi.wsgiApp(environ, start): 
    56             yield chunk 
    57     except (KeyboardInterrupt, SystemExit): 
    58         raise 
    59     except Exception, x: 
    60         # We should only reach this point if server.throw_errors is True. 
    61         if not started[0]: 
    62             start_response("500 Server Error", []) 
    63         yield "THROWN ERROR: %s" % x.__class__.__name__ 
    64  
    65  
    66 class TestWSGI(_cpwsgi.WSGIServer): 
    67     """Wrapper for WSGI server so we can test thrown errors.""" 
    68      
    69     def __init__(self): 
    70         _cpwsgi.WSGIServer.__init__(self) 
    71         self.mount_points = [(base, error_middleware) 
    72                              for base, wsgiapp in self.mount_points] 
    7327 
    7428 
     
    8337        sys.exit() 
    8438     
    85     def _getRequest(self, url, headers, method, body): 
    86         # Like getPage, but for serverless requests. 
    87         webtest.ServerError.on = False 
    88         self.url = url 
    89          
    90         requestLine = "%s %s HTTP/1.1" % (method.upper(), url) 
    91         headers = webtest.cleanHeaders(headers, method, body, 
    92                                        self.HOST, self.PORT) 
    93         if body is not None: 
    94             body = StringIO.StringIO(body) 
    95          
    96         request = cherrypy.server.request((self.HOST, self.PORT), self.HOST, "http") 
    97         response = request.run(requestLine, headers, body) 
    98          
    99         self.status = response.status 
    100         self.headers = response.header_list 
    101          
    102         # Build a list of request cookies from the previous response cookies. 
    103         self.cookies = [('Cookie', v) for k, v in self.headers 
    104                         if k.lower() == 'set-cookie'] 
    105          
    106         try: 
    107             newbody = [] 
    108             for chunk in response.body: 
    109                 newbody.append(chunk) 
    110             request.close() 
    111         except Exception, ex: 
    112             if cherrypy.config.get("stream_response", False): 
    113                 try: 
    114                     request.close() 
    115                 except: 
    116                     cherrypy.log(cherrypy._cputil.formatExc()) 
    117                 # Pass the error through 
    118                 raise ex 
    119              
    120             s, h, b = cherrypy._cputil.bareError() 
    121             # Don't reset status or headers; we're emulating an error which 
    122             # occurs after status and headers have been written to the client. 
    123             for chunk in b: 
    124                 newbody.append(chunk) 
    125         self.body = "".join(newbody) 
    126          
    127         if webtest.ServerError.on: 
    128             self.tearDown() 
    129             raise webtest.ServerError() 
    130      
    13139    def tearDown(self): 
    13240        pass 
    13341     
    134     def getPage(self, url, headers=None, method="GET", body=None): 
    135         """Open the url with debugging support. Return status, headers, body.""" 
    136         # Install a custom error handler, so errors in the server will: 
    137         # 1) show server tracebacks in the test output, and 
    138         # 2) stop the HTTP request (if any) and ignore further assertions. 
    139         cherrypy.root._cp_on_error = onerror 
    140         # Backward compatibility: 
    141         cherrypy.root._cpOnError = onerror 
    142          
     42    def getPage(self, url, headers=None, method="GET", body=None, protocol="HTTP/1.1"): 
     43        """Open the url. Return status, headers, body.""" 
    14344        if self.mount_point: 
    14445            url = httptools.urljoin(self.mount_point, url) 
    14546         
    146         if cherrypy.server.httpserver is None: 
    147             self._getRequest(url, headers, method, body) 
    148         else: 
    149             webtest.WebCase.getPage(self, url, headers, method, body) 
     47        webtest.WebCase.getPage(self, url, headers, method, body, protocol) 
    15048     
    15149    def assertErrorPage(self, status, message=None, pattern=''): 
     
    20199    setConfig(conf) 
    202100    cherrypy.server.start_with_callback(_run_test_suite_thread, 
    203             args = (moduleNames, conf), server_class = server) 
     101                                        args = (moduleNames, conf), 
     102                                        server_class = server) 
    204103 
    205104def _run_test_suite_thread(moduleNames, conf): 
     
    212111        setConfig(conf) 
    213112         
     113        m = __import__(testmod, globals(), locals()) 
     114        setup = getattr(m, "setup_server", None) 
     115        if setup: 
     116            setup() 
    214117        suite = CPTestLoader.loadTestsFromName(testmod) 
    215118        CPTestRunner.run(suite) 
    216119    thread.interrupt_main() 
    217120 
    218 def testmain(server=None, conf=None): 
     121def testmain(conf=None, *args, **kwargs): 
    219122    """Run __main__ as a test module, with webtest debugging.""" 
    220123    if conf is None: 
    221124        conf = {} 
    222125    setConfig(conf) 
    223     cherrypy.server.start_with_callback(_test_main_thread, 
    224             server_class = server) 
     126    cherrypy.server.start_with_callback(_test_main_thread, *args, **kwargs) 
    225127 
    226128def _test_main_thread(): 
  • trunk/cherrypy/test/test.py

    r1005 r1017  
    1818 
    1919class TestHarness(object): 
    20      
    2120    """A test harness for the CherryPy framework and CherryPy applications.""" 
    2221     
    23     # The first server in the list is the default server. 
    24     available_servers = {'serverless': (0, "Serverless", None), 
    25                          'wsgi': (1, "Native WSGI Server", 
    26                                   "cherrypy.test.helper.TestWSGI"), 
     22    def __init__(self, tests=None, server=None, protocol="HTTP/1.1", port=8000): 
     23        """Constructor to populate the TestHarness instance. 
     24         
     25        tests should be a list of module names (strings). 
     26        """ 
     27        self.protocol = protocol 
     28        self.port = port 
     29        self.server = server 
     30        self.tests = tests or [] 
     31     
     32    def run(self, conf=None): 
     33        """Run the test harness.""" 
     34        import cherrypy 
     35        v = sys.version.split()[0] 
     36        print "Python version used to run this test script:", v 
     37        print "CherryPy version", cherrypy.__version__ 
     38        print 
     39         
     40        if conf is None: 
     41            conf = {'server.socket_host': '127.0.0.1', 
     42                    'server.socket_port': self.port, 
     43                    'server.thread_pool': 10, 
     44                    'server.log_to_screen': False, 
     45                    'server.environment': "production", 
     46                    'server.show_tracebacks': True, 
     47                    } 
     48        elif isinstance(conf, basestring): 
     49            conf = cherrypy.config.dict_from_config_file(conf) 
     50         
     51        conf['server.protocol_version'] = self.protocol 
     52        self._run(conf) 
     53     
     54    def _run(self, conf): 
     55        # helper must be imported lazily so the coverage tool 
     56        # can run against module-level statements within cherrypy. 
     57        # Also, we have to do a relative import here, not 
     58        # "from cherrypy.test import helper", because the latter 
     59        # would stick a second instance of webtest in sys.modules, 
     60        # and we wouldn't be able to globally override the port anymore. 
     61        import helper 
     62        webtest.WebCase.PORT = self.port 
     63        print 
     64        print "Running tests:", self.server 
     65        helper.run_test_suite(self.tests, self.server, conf) 
     66 
     67 
     68class CommandLineParser(object): 
     69    available_servers = {'wsgi': "cherrypy._cpwsgi.WSGIServer", 
     70                         'modpy': "modpy", 
    2771                         } 
    2872    default_server = "wsgi" 
    2973     
    30     def __init__(self, available_tests): 
     74    def __init__(self, available_tests, args=sys.argv[1:]): 
    3175        """Constructor to populate the TestHarness instance. 
    3276         
    3377        available_tests should be a list of module names (strings). 
    34         """ 
    35         self.available_tests = available_tests 
    36          
    37         self.cover = False 
    38         self.profile = False 
    39         self.protocol = "HTTP/1.0" 
    40         self.basedir = None 
    41         self.PORT = 8000 
    42          
    43         self.servers = [] 
    44         self.tests = [] 
    45      
    46     def load(self, args=sys.argv[1:]): 
    47         """Populate a TestHarness from sys.argv. 
    4878         
    4979        args defaults to sys.argv[1:], but you can provide a different 
    5080            set of args if you like. 
    5181        """ 
    52          
    53         longopts = ['cover', 'profile', '1.1', 'help', 
    54                     'basedir=', 'all', 'port='] 
     82        self.available_tests = available_tests 
     83        self.cover = False 
     84        self.profile = False 
     85        self.server = None 
     86        self.port = 8080 
     87        self.protocol = "HTTP/1.1" 
     88         
     89        longopts = ['cover', 'profile', '1.1', 'help', 'basedir=', 'port=', 
     90                    'server='] 
    5591        longopts.extend(self.available_servers) 
    5692        longopts.extend(self.available_tests) 
     
    6298            sys.exit(2) 
    6399         
    64         self.cover = False 
    65         self.profile = False 
    66         self.protocol = "HTTP/1.0" 
    67         self.basedir = None 
    68          
    69         self.servers = [] 
    70100        self.tests = [] 
    71101         
     
    78108            elif o == "--profile": 
    79109                self.profile = True 
    80             elif o == "--1.1": 
    81                 self.protocol = "HTTP/1.1
     110            elif o == "--1.0": 
     111                self.protocol = "HTTP/1.0
    82112            elif o == "--basedir": 
    83113                self.basedir = a 
    84             elif o == "--all": 
    85                 self.servers = self.available_servers.keys() 
    86114            elif o == "--port": 
    87                 self.PORT = int(a) 
     115                self.port = int(a) 
     116            elif o == "--server": 
     117                if a in self.available_servers: 
     118                    a = self.available_servers[a] 
     119                self.server = a 
    88120            else: 
    89121                o = o[2:] 
    90                 if o in self.available_servers and o not in self.servers: 
    91                     self.servers.append(o) 
    92                 elif o in self.available_tests and o not in self.tests: 
     122                if o in self.available_tests and o not in self.tests: 
    93123                    self.tests.append(o) 
    94124         
     
    99129            sys.exit(2) 
    100130         
    101         if not self.servers
    102             self.servers = [self.default_server] 
     131        if not self.server
     132            self.server = self.available_servers[self.default_server] 
    103133         
    104134        if not self.tests: 
     
    110140        print """CherryPy Test Program 
    111141    Usage: 
    112         test.py --servers* --1.1 --cover --basedir=path --profile --tests** 
     142        test.py --server=* --1.1 --cover --basedir=path --profile --tests** 
    113143         
    114144    """ 
    115145        print '    * servers:' 
    116         s = [(val, name) for name, val in self.available_servers.iteritems()] 
    117         s.sort() 
    118         for val, name in s: 
     146        for name, val in self.available_servers.iteritems(): 
    119147            if name == self.default_server: 
    120                 print '        --' + name, '(default)' 
     148                print '        --%s: %s (default)' % (name, val) 
    121149            else: 
    122                 print '        --' + name 
    123          
    124         print """        --all (runs all servers in order) 
     150                print '        --%s: %s' % (name, val) 
     151         
     152        print """ 
    125153     
    126154    --1.1: use HTTP/1.1 servers instead of default HTTP/1.0 
     
    220248    def run(self, conf=None): 
    221249        """Run the test harness.""" 
    222         self.load() 
    223          
    224250        # Start the coverage tool before importing cherrypy, 
    225251        # so module-level global statements are covered. 
     
    227253            self.start_coverage() 
    228254         
    229         import cherrypy 
    230         v = sys.version.split()[0] 
    231         print "Python version used to run this test script:", v 
    232         print "CherryPy version", cherrypy.__version__ 
    233         print 
    234          
    235         if conf is None: 
    236             conf = {'server.socket_host': '127.0.0.1', 
    237                     'server.socket_port': self.PORT, 
    238                     'server.thread_pool': 10, 
    239                     'server.log_to_screen': False, 
    240                     'server.environment': "production", 
    241                     'server.show_tracebacks': True, 
    242                     } 
    243         elif isinstance(conf, basestring): 
    244             conf = cherrypy.config.dict_from_config_file(conf) 
    245          
    246         conf['server.protocol_version'] = self.protocol 
    247          
    248255        if self.profile: 
    249256            conf['profiling.on'] = True 
    250257         
    251         self._run_all_servers(conf) 
     258        if self.server == 'modpy': 
     259            import modpy 
     260            modpy.ModPythonTestHarness(self.tests, self.server, 
     261                                       self.protocol, self.port).run(conf) 
     262        else: 
     263            TestHarness(self.tests, self.server, 
     264                        self.protocol, self.port).run(conf) 
    252265         
    253266        if self.profile: 
     
    259272        if self.cover: 
    260273            self.stop_coverage() 
    261      
    262     def _run_all_servers(self, conf): 
    263         # helper must be imported lazily so the coverage tool 
    264         # can run against module-level statements within cherrypy. 
    265         # Also, we have to do a relative import here, not 
    266         # "from cherrypy.test import helper", because the latter 
    267         # would stick a second instance of webtest in sys.modules, 
    268         # and we wouldn't be able to globally override the port anymore. 
    269         import helper 
    270         s = [self.available_servers[name] for name in self.servers] 
    271         s.sort() 
    272         webtest.WebCase.PORT = self.PORT 
    273         for priority, name, cls in s: 
    274             print 
    275             print "Running tests:", name 
    276             helper.run_test_suite(self.tests, cls, conf) 
    277  
    278  
    279 class CPTestHarness(TestHarness): 
    280      
    281     def _run_all_servers(self, conf): 
    282         # helper must be imported lazily so the coverage tool 
    283         # can run against module-level statements within cherrypy. 
    284         # Also, we have to do a relative import here, not 
    285         # "from cherrypy.test import helper", because the latter 
    286         # would stick a second instance of webtest in sys.modules, 
    287         # and we wouldn't be able to globally override the port anymore. 
    288         import helper, test_states 
    289         s = [self.available_servers[name] for name in self.servers] 
    290         s.sort() 
    291         webtest.WebCase.PORT = self.PORT 
    292         for priority, name, cls in s: 
    293             print 
    294             print "Running tests:", name 
    295             reload(test_states) 
    296             test_states.run(cls, conf) 
    297             helper.run_test_suite(self.tests, cls, conf) 
     274 
    298275 
    299276def prefer_parent_path(): 
     
    320297        'test_gzip_filter', 
    321298        'test_logdebuginfo_filter', 
     299        'test_objectmapping', 
    322300        'test_response_headers_filter', 
    323         'test_objectmapping', 
    324301        'test_static_filter', 
    325         'test_tutorials', 
     302##        'test_tutorials', 
    326303        'test_virtualhost_filter', 
    327304        'test_session_filter', 
    328305        'test_sessionauthenticate_filter', 
     306##        'test_states', 
    329307        'test_xmlrpc_filter', 
    330308        'test_wsgiapp_filter', 
    331309    ] 
    332     CPTestHarness(testList).run() 
     310    CommandLineParser(testList).run() 
    333311     
    334312    print 
  • trunk/cherrypy/test/test_baseurl_filter.py

    r910 r1017  
    55 
    66 
    7 class Root: 
    8     def index(self): 
    9         raise cherrypy.HTTPRedirect('dummy') 
    10     index.exposed = True 
     7def setup_server(): 
     8    class Root: 
     9        def index(self): 
     10            raise cherrypy.HTTPRedirect('dummy') 
     11        index.exposed = True 
     12     
     13    cherrypy.tree.mount(Root()) 
     14    cherrypy.config.update({ 
     15            'server.environment': 'production', 
     16            'server.log_to_screen': False, 
     17            'base_url_filter.on': True, 
     18            'base_url_filter.base_url': 'http://www.mydomain.com' 
     19    }) 
    1120 
    12 cherrypy.root = Root() 
    13 cherrypy.config.update({ 
    14         'server.environment': 'production', 
    15         'server.log_to_screen': False, 
    16         'base_url_filter.on': True, 
    17         'base_url_filter.base_url': 'http://www.mydomain.com' 
    18 }) 
    1921 
    2022import helper 
     
    2931 
    3032if __name__ == '__main__': 
     33    setup_server() 
    3134    helper.testmain() 
    32  
  • trunk/cherrypy/test/test_cache_filter.py

    r906 r1017  
    66 
    77 
    8 class Root: 
    9     def __init__(self): 
    10         cherrypy.counter = 0 
    11      
    12     def index(self): 
    13         cherrypy.counter += 1 
    14         msg = "visit #%s" % cherrypy.counter 
    15         return msg 
    16     index.exposed = True 
     8def setup_server(): 
     9    class Root: 
     10        def __init__(self): 
     11            cherrypy.counter = 0 
     12         
     13        def index(self): 
     14            cherrypy.counter += 1 
     15            msg = "visit #%s" % cherrypy.counter 
     16            return msg 
     17        index.exposed = True 
    1718 
    18 cherrypy.root = Root() 
    19 cherrypy.config.update({ 
    20         'server.log_to_screen': False, 
    21         'server.environment': 'production', 
    22         'cache_filter.on': True, 
    23 }) 
     19    cherrypy.root = Root() 
     20    cherrypy.config.update({ 
     21            'server.log_to_screen': False, 
     22            'server.environment': 'production', 
     23            'cache_filter.on': True, 
     24    }) 
    2425 
    2526 
     
    3536 
    3637if __name__ == '__main__': 
     38    setup_server() 
    3739    helper.testmain() 
    3840 
  • trunk/cherrypy/test/test_combinedfilters.py

    r856 r1017  
    77europoundUnicode = u'\x80\xa3' 
    88 
    9 class Root: 
    10     def index(self): 
    11         yield u"Hello," 
    12         yield u"world" 
    13         yield europoundUnicode 
    14     index.exposed = True 
     9def setup_server(): 
     10    class Root: 
     11        def index(self): 
     12            yield u"Hello," 
     13            yield u"world" 
     14            yield europoundUnicode 
     15        index.exposed = True 
    1516 
    16 cherrypy.root = Root() 
    17 cherrypy.config.update({ 
    18         'server.log_to_screen': False, 
    19         'server.environment': 'production', 
    20         'gzip_filter.on': True, 
    21         'encoding_filter.on': True, 
    22 }) 
     17    cherrypy.root = Root() 
     18    cherrypy.config.update({ 
     19            'server.log_to_screen': False, 
     20            'server.environment': 'production', 
     21            'gzip_filter.on': True, 
     22            'encoding_filter.on': True, 
     23    }) 
    2324 
    2425import helper 
     
    3839 
    3940if __name__ == '__main__': 
     41    setup_server() 
    4042    helper.testmain() 
  • trunk/cherrypy/test/test_config.py

    r1004 r1017  
    77 
    88 
    9 class Root: 
    10     def index(self, key): 
    11         return cherrypy.config.get(key, "None") 
    12     index.exposed = True 
    13     global_ = index 
    14     xyz = index 
     9def setup_server(): 
     10     
     11    class Root: 
     12        def index(self, key): 
     13            return cherrypy.config.get(key, "None") 
     14        index.exposed = True 
     15        global_ = index 
     16        xyz = index 
     17     
     18    class Foo: 
     19        def index(self, key): 
     20            return cherrypy.config.get(key, "None") 
     21        index.exposed = True 
     22        bar = index 
     23        nex = index 
     24     
     25    class Env: 
     26        def index(self, key): 
     27            return str(cherrypy.config.get(key, "None")) 
     28        index.exposed = True 
     29        prod = index 
     30        embed = index 
     31         
     32        def wrong(self): 
     33            conf = "\n[global]\nserver.environment = production\n" 
     34            cherrypy.config.update(file=StringIO.StringIO(conf)) 
     35        wrong.exposed=True 
     36     
     37    cherrypy.tree.mount(Root()) 
     38    cherrypy.root.foo = Foo() 
     39     
     40    cherrypy.config.update({ 
     41        'global': {'server.log_to_screen': False, 
     42                   'server.environment': 'production', 
     43                   'server.show_tracebacks': True, 
     44                   }, 
     45        '/': { 
     46            'foo': 'this', 
     47            'bar': 'that', 
     48            }, 
     49        '/foo': { 
     50            'foo': 'this2', 
     51            'baz': 'that2', 
     52            }, 
     53        '/foo/bar': { 
     54            'foo': 'this3', 
     55            'bax': 'this4', 
     56            }, 
     57    }) 
    1558 
    16 class Foo: 
    17     def index(self, key): 
    18         return cherrypy.config.get(key, "None") 
    19     index.exposed = True 
    20     bar = index 
    21     nex = index 
     59    _env_conf = {'/': {'server.environment': 'development'}, 
     60                 '/prod': {'server.environment': 'production'}, 
     61                 '/embed': {'server.environment': 'embedded'}, 
     62                 } 
     63    cherrypy.tree.mount(Env(), "/env", _env_conf) 
    2264 
    23 class Env: 
    24     def index(self, key): 
    25         return str(cherrypy.config.get(key, "None")) 
    26     index.exposed = True 
    27     prod = index 
    28     embed = index 
     65    # Shortcut syntax--should get put in the "global" bucket 
     66    cherrypy.config.update({'luxuryyacht': 'throatwobblermangrove'}) 
    2967 
    30 cherrypy.tree.mount(Root()) 
    31 cherrypy.root.foo = Foo() 
    3268 
    33 cherrypy.config.update({ 
    34     'global': {'server.log_to_screen': False, 
    35                'server.environment': 'production', 
    36                'server.show_tracebacks': True, 
    37                }, 
    38     '/': { 
    39         'foo': 'this', 
    40         'bar': 'that', 
    41         }, 
    42     '/foo': { 
    43         'foo': 'this2', 
    44         'baz': 'that2', 
    45         }, 
    46     '/foo/bar': { 
    47         'foo': 'this3', 
    48         'bax': 'this4', 
    49         }, 
    50 }) 
    51  
    52 _env_conf = {'/': {'server.environment': 'development'}, 
    53              '/prod': {'server.environment': 'production'}, 
    54              '/embed': {'server.environment': 'embedded'}, 
    55              } 
    56 cherrypy.tree.mount(Env(), "/env", _env_conf) 
    57  
    58 # Shortcut syntax--should get put in the "global" bucket 
    59 cherrypy.config.update({'luxuryyacht': 'throatwobblermangrove'}) 
     69#                             Client-side code                             # 
    6070 
    6171import helper 
     
    6575    def testConfig(self): 
    6676        tests = [ 
    67             ('*',        'luxuryyacht', 'throatwobblermangrove'), 
     77##            ('*',        'luxuryyacht', 'throatwobblermangrove'), 
    6878            ('/',        'nex', 'None'), 
    6979            ('/',        'foo', 'this'), 
     
    8393     
    8494    def testUnrepr(self): 
    85         self.assertRaises(cherrypy.WrongConfigValue, cherrypy.config.update, 
    86                           file=StringIO.StringIO(""
    87 [global] 
    88 server.environment = production 
    89 """)
     95        err = ('WrongConfigValue: ("section: ' 
     96               "'global', option: 'server.environment', value: 'production'
     97               '''", 'UnknownType', ('production',))''') 
     98        self.getPage("/env/wrong") 
     99        self.assertErrorPage(500, pattern=err
    90100     
    91101    def testEnvironments(self): 
     
    105115 
    106116if __name__ == '__main__': 
     117    setup_server() 
    107118    helper.testmain() 
  • trunk/cherrypy/test/test_core.py

    r1010 r1017  
    77from cherrypy.lib import cptools, httptools 
    88import types 
     9 
    910import os 
    1011localDir = os.path.dirname(__file__) 
    11  
    12  
    13 class Root: 
    14      
    15     def index(self): 
    16         return "hello" 
    17     index.exposed = True 
    18      
    19     def andnow(self): 
    20         return "the larch" 
    21     andnow.exposed = True 
    22      
    23     def global_(self): 
    24         pass 
    25     global_.exposed = True 
    26  
    27 cherrypy.root = Root() 
    28  
    29  
    30 class TestType(type): 
    31     """Metaclass which automatically exposes all functions in each subclass, 
    32     and adds an instance of the subclass as an attribute of cherrypy.root. 
    33     """ 
    34     def __init__(cls, name, bases, dct): 
    35         type.__init__(name, bases, dct) 
    36         for value in dct.itervalues(): 
    37             if isinstance(value, types.FunctionType): 
    38                 value.exposed = True 
    39         setattr(cherrypy.root, name.lower(), cls()) 
    40 class Test(object): 
    41     __metaclass__ = TestType 
    42  
    43  
    44 class Params(Test): 
    45      
    46     def index(self, thing): 
    47         return repr(thing) 
    48      
    49     def ismap(self, x, y): 
    50         return "Coordinates: %s, %s" % (x, y) 
    51      
    52     def default(self, *args, **kwargs): 
    53         return "args: %s kwargs: %s" % (args, kwargs) 
    54  
    55  
    56 class Status(Test): 
    57      
    58     def index(self): 
    59         return "normal" 
    60      
    61     def blank(self): 
    62         cherrypy.response.status = "" 
    63      
    64     # According to RFC 2616, new status codes are OK as long as they 
    65     # are between 100 and 599. 
    66      
    67     # Here is an illegal code... 
    68     def illegal(self): 
    69         cherrypy.response.status = 781 
    70         return "oops" 
    71      
    72     # ...and here is an unknown but legal code. 
    73     def unknown(self): 
    74         cherrypy.response.status = "431 My custom error" 
    75         return "funky" 
    76      
    77     # Non-numeric code 
    78     def bad(self): 
    79         cherrypy.response.status = "error" 
    80         return "bad news" 
    81  
    82  
    83 class Redirect(Test): 
    84      
    85     class Error: 
    86         def _cp_on_error(self): 
    87             raise cherrypy.HTTPRedirect("/errpage") 
    88          
    89         def index(self): 
    90             raise NameError() 
    91         index.exposed = True 
    92     error = Error() 
    93      
    94     def index(self): 
    95         return "child" 
    96      
    97     def by_code(self, code): 
    98         raise cherrypy.HTTPRedirect("somewhere else", code) 
    99      
    100     def nomodify(self): 
    101         raise cherrypy.HTTPRedirect("", 304) 
    102      
    103     def proxy(self): 
    104         raise cherrypy.HTTPRedirect("proxy", 305) 
    105      
    106     def stringify(self): 
    107         return str(cherrypy.HTTPRedirect("/")) 
    108  
    109  
    110 class LoginFilter: 
    111      
    112     def before_main(self): 
    113         if cherrypy.config.get("auth.on", False): 
    114             if not getattr(cherrypy.request, "login", None): 
    115                 raise cherrypy.InternalRedirect("/internalredirect/login") 
    116  
    117 class InternalRedirect(Test): 
    118      
    119     _cp_filters = [LoginFilter()] 
    120      
    121     def index(self): 
    122         raise cherrypy.InternalRedirect("/") 
    123      
    124     def petshop(self, user_id): 
    125         if user_id == "parrot": 
    126             # Trade it for a slug when redirecting 
    127             raise cherrypy.InternalRedirect('/image/getImagesByUser', 
    128                                            "user_id=slug") 
    129         elif user_id == "terrier": 
    130             # Trade it for a fish when redirecting 
    131             raise cherrypy.InternalRedirect('/image/getImagesByUser', 
    132                                            {"user_id": "fish"}) 
    133         else: 
    134             raise cherrypy.InternalRedirect('/image/getImagesByUser') 
    135      
    136     def secure(self): 
    137         return "Welcome!" 
    138      
    139     def login(self): 
    140         return "Please log in" 
    141  
    142  
    143 class Image(Test): 
    144      
    145     def getImagesByUser(self, user_id): 
    146         return "0 images for %s" % user_id 
    147  
    148  
    149 class Flatten(Test): 
    150      
    151     def as_string(self): 
    152         return "content" 
    153      
    154     def as_list(self): 
    155         return ["con", "tent"] 
    156      
    157     def as_yield(self): 
    158         yield "content" 
    159      
    160     def as_dblyield(self): 
    161         yield self.as_yield() 
    162      
    163     def as_refyield(self): 
    164         for chunk in self.as_yield(): 
    165             yield chunk 
    166  
    167  
    168 class Error(Test): 
    169      
    170     def custom(self): 
    171         raise cherrypy.HTTPError(404, "No, <b>really</b>, not found!") 
    172      
    173     def noexist(self): 
    174         raise cherrypy.HTTPError(404, "No, <b>really</b>, not found!") 
    175      
    176     def page_method(self): 
    177         raise ValueError() 
    178      
    179     def page_yield(self): 
    180         yield "howdy" 
    181         raise ValueError() 
    182      
    183     def page_streamed(self): 
    184         yield "word up" 
    185         raise ValueError() 
    186         yield "very oops" 
    187      
    188     def cause_err_in_finalize(self): 
    189         # Since status must start with an int, this should error. 
    190         cherrypy.response.status = "ZOO OK" 
    191      
    192     def log_unhandled(self): 
    193         raise ValueError() 
    194      
    195     def rethrow(self): 
    196         """Test that an error raised here will be thrown out to the server.""" 
    197         raise ValueError() 
    198  
    199  
    200 class Ranges(Test): 
    201      
    202     def get_ranges(self): 
    203         h = cherrypy.request.headers.get('Range') 
    204         return repr(httptools.getRanges(h, 8)) 
    205      
    206     def slice_file(self): 
    207         path = os.path.join(os.getcwd(), os.path.dirname(__file__)) 
    208         return cptools.serveFile(os.path.join(path, "static/index.html")) 
    209  
    210  
    211 class Expect(Test): 
    212      
    213     def expectation_failed(self): 
    214         expect = cherrypy.request.headers.elements("Expect") 
    215         if expect and expect[0].value != '100-continue': 
    216             raise cherrypy.HTTPError(400) 
    217         raise cherrypy.HTTPError(417, 'Expectation Failed') 
    218  
    219 class Headers(Test): 
    220      
    221     def doubledheaders(self): 
    222         # From http://www.cherrypy.org/ticket/165: 
    223         # "header field names should not be case sensitive sayes the rfc. 
    224         # if i set a headerfield in complete lowercase i end up with two 
    225         # header fields, one in lowercase, the other in mixed-case." 
    226          
    227         # Set the most common headers 
    228         hMap = cherrypy.response.headers 
    229         hMap['content-type'] = "text/html" 
    230         hMap['content-length'] = 18 
    231         hMap['server'] = 'CherryPy headertest' 
    232         hMap['location'] = ('%s://127.0.0.1:%s/headers/' 
    233                             % (cherrypy.request.remote_port, 
    234                                cherrypy.request.scheme)) 
    235          
    236         # Set a rare header for fun 
    237         hMap['Expires'] = 'Thu, 01 Dec 2194 16:00:00 GMT' 
    238          
    239         return "double header test" 
    240  
    241  
    242 class HeaderElements(Test): 
    243      
    244     def get_elements(self, headername): 
    245         e = cherrypy.request.headers.elements(headername) 
    246         return "\n".join([str(x) for x in e]) 
    247  
     12log_file = os.path.join(localDir, "error.log") 
     13log_access_file = os.path.join(localDir, "access.log") 
    24814 
    24915defined_http_methods = ("OPTIONS", "GET", "HEAD", "POST", "PUT", "DELETE", 
    25016                        "TRACE", "CONNECT") 
    251 class Method(Test): 
    252      
    253     def index(self): 
    254         m = cherrypy.request.method 
    255         if m in defined_http_methods: 
    256             return m 
    257          
    258         if m == "LINK": 
    259             raise cherrypy.HTTPError(405) 
    260         else: 
    261             raise cherrypy.HTTPError(501) 
    262      
    263     def parameterized(self, data): 
    264         return data 
    265      
    266     def request_body(self): 
    267         # This should be a file object (temp file), 
    268         # which CP will just pipe back out if we tell it to. 
    269         return cherrypy.request.body 
    270  
    271 class Divorce: 
    272     """HTTP Method handlers shouldn't collide with normal method names. 
    273