Changeset 1017
- Timestamp:
- 03/26/06 16:14:11
- Files:
-
- trunk/cherrypy/test/helper.py (modified) (5 diffs)
- trunk/cherrypy/test/modpy.py (added)
- trunk/cherrypy/test/static/dirback.jpg (added)
- trunk/cherrypy/test/test.py (modified) (9 diffs)
- trunk/cherrypy/test/test_baseurl_filter.py (modified) (2 diffs)
- trunk/cherrypy/test/test_cache_filter.py (modified) (2 diffs)
- trunk/cherrypy/test/test_combinedfilters.py (modified) (2 diffs)
- trunk/cherrypy/test/test_config.py (modified) (4 diffs)
- trunk/cherrypy/test/test_core.py (modified) (22 diffs)
- trunk/cherrypy/test/test_custom_filters.py (modified) (4 diffs)
- trunk/cherrypy/test/test_decodingencoding_filter.py (modified) (2 diffs)
- trunk/cherrypy/test/test_gzip_filter.py (modified) (2 diffs)
- trunk/cherrypy/test/test_http.py (modified) (3 diffs)
- trunk/cherrypy/test/test_logdebuginfo_filter.py (modified) (2 diffs)
- trunk/cherrypy/test/test_objectmapping.py (modified) (2 diffs)
- trunk/cherrypy/test/test_response_headers_filter.py (modified) (2 diffs)
- trunk/cherrypy/test/test_session_filter.py (modified) (3 diffs)
- trunk/cherrypy/test/test_sessionauthenticate_filter.py (modified) (3 diffs)
- trunk/cherrypy/test/test_static_filter.py (modified) (3 diffs)
- trunk/cherrypy/test/test_virtualhost_filter.py (modified) (2 diffs)
- trunk/cherrypy/test/test_wsgiapp_filter.py (modified) (2 diffs)
- trunk/cherrypy/test/test_xmlrpc_filter.py (modified) (3 diffs)
- trunk/cherrypy/test/webtest.py (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/cherrypy/test/helper.py
r1014 r1017 5 5 6 6 Usage: 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 calls11 run_test_suite, possibly more than once. CP applications may also12 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. 13 13 """ 14 14 … … 18 18 # or vice-versa, unless you *really* know what you're doing. 19 19 20 import os, os.path21 20 import re 22 import socket23 import StringIO24 21 import sys 25 22 import thread 26 import threading27 import time28 import types29 23 30 24 import cherrypy 31 from cherrypy import _cpwsgi32 25 from cherrypy.lib import httptools 33 26 import 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] = True52 start_response(s, h, exc)53 54 try:55 for chunk in _cpwsgi.wsgiApp(environ, start):56 yield chunk57 except (KeyboardInterrupt, SystemExit):58 raise59 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]73 27 74 28 … … 83 37 sys.exit() 84 38 85 def _getRequest(self, url, headers, method, body):86 # Like getPage, but for serverless requests.87 webtest.ServerError.on = False88 self.url = url89 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.status100 self.headers = response.header_list101 102 # Build a list of request cookies from the previous response cookies.103 self.cookies = [('Cookie', v) for k, v in self.headers104 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 through118 raise ex119 120 s, h, b = cherrypy._cputil.bareError()121 # Don't reset status or headers; we're emulating an error which122 # 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 131 39 def tearDown(self): 132 40 pass 133 41 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.""" 143 44 if self.mount_point: 144 45 url = httptools.urljoin(self.mount_point, url) 145 46 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) 150 48 151 49 def assertErrorPage(self, status, message=None, pattern=''): … … 201 99 setConfig(conf) 202 100 cherrypy.server.start_with_callback(_run_test_suite_thread, 203 args = (moduleNames, conf), server_class = server) 101 args = (moduleNames, conf), 102 server_class = server) 204 103 205 104 def _run_test_suite_thread(moduleNames, conf): … … 212 111 setConfig(conf) 213 112 113 m = __import__(testmod, globals(), locals()) 114 setup = getattr(m, "setup_server", None) 115 if setup: 116 setup() 214 117 suite = CPTestLoader.loadTestsFromName(testmod) 215 118 CPTestRunner.run(suite) 216 119 thread.interrupt_main() 217 120 218 def testmain( server=None, conf=None):121 def testmain(conf=None, *args, **kwargs): 219 122 """Run __main__ as a test module, with webtest debugging.""" 220 123 if conf is None: 221 124 conf = {} 222 125 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) 225 127 226 128 def _test_main_thread(): trunk/cherrypy/test/test.py
r1005 r1017 18 18 19 19 class TestHarness(object): 20 21 20 """A test harness for the CherryPy framework and CherryPy applications.""" 22 21 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 68 class CommandLineParser(object): 69 available_servers = {'wsgi': "cherrypy._cpwsgi.WSGIServer", 70 'modpy': "modpy", 27 71 } 28 72 default_server = "wsgi" 29 73 30 def __init__(self, available_tests ):74 def __init__(self, available_tests, args=sys.argv[1:]): 31 75 """Constructor to populate the TestHarness instance. 32 76 33 77 available_tests should be a list of module names (strings). 34 """35 self.available_tests = available_tests36 37 self.cover = False38 self.profile = False39 self.protocol = "HTTP/1.0"40 self.basedir = None41 self.PORT = 800042 43 self.servers = []44 self.tests = []45 46 def load(self, args=sys.argv[1:]):47 """Populate a TestHarness from sys.argv.48 78 49 79 args defaults to sys.argv[1:], but you can provide a different 50 80 set of args if you like. 51 81 """ 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='] 55 91 longopts.extend(self.available_servers) 56 92 longopts.extend(self.available_tests) … … 62 98 sys.exit(2) 63 99 64 self.cover = False65 self.profile = False66 self.protocol = "HTTP/1.0"67 self.basedir = None68 69 self.servers = []70 100 self.tests = [] 71 101 … … 78 108 elif o == "--profile": 79 109 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" 82 112 elif o == "--basedir": 83 113 self.basedir = a 84 elif o == "--all":85 self.servers = self.available_servers.keys()86 114 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 88 120 else: 89 121 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: 93 123 self.tests.append(o) 94 124 … … 99 129 sys.exit(2) 100 130 101 if not self.server s:102 self.server s =[self.default_server]131 if not self.server: 132 self.server = self.available_servers[self.default_server] 103 133 104 134 if not self.tests: … … 110 140 print """CherryPy Test Program 111 141 Usage: 112 test.py --server s* --1.1 --cover --basedir=path --profile --tests**142 test.py --server=* --1.1 --cover --basedir=path --profile --tests** 113 143 114 144 """ 115 145 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(): 119 147 if name == self.default_server: 120 print ' -- ' + name, '(default)'148 print ' --%s: %s (default)' % (name, val) 121 149 else: 122 print ' -- ' + name123 124 print """ --all (runs all servers in order)150 print ' --%s: %s' % (name, val) 151 152 print """ 125 153 126 154 --1.1: use HTTP/1.1 servers instead of default HTTP/1.0 … … 220 248 def run(self, conf=None): 221 249 """Run the test harness.""" 222 self.load()223 224 250 # Start the coverage tool before importing cherrypy, 225 251 # so module-level global statements are covered. … … 227 253 self.start_coverage() 228 254 229 import cherrypy230 v = sys.version.split()[0]231 print "Python version used to run this test script:", v232 print "CherryPy version", cherrypy.__version__233 print234 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.protocol247 248 255 if self.profile: 249 256 conf['profiling.on'] = True 250 257 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) 252 265 253 266 if self.profile: … … 259 272 if self.cover: 260 273 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 298 275 299 276 def prefer_parent_path(): … … 320 297 'test_gzip_filter', 321 298 'test_logdebuginfo_filter', 299 'test_objectmapping', 322 300 'test_response_headers_filter', 323 'test_objectmapping',324 301 'test_static_filter', 325 'test_tutorials',302 ## 'test_tutorials', 326 303 'test_virtualhost_filter', 327 304 'test_session_filter', 328 305 'test_sessionauthenticate_filter', 306 ## 'test_states', 329 307 'test_xmlrpc_filter', 330 308 'test_wsgiapp_filter', 331 309 ] 332 C PTestHarness(testList).run()310 CommandLineParser(testList).run() 333 311 334 312 print trunk/cherrypy/test/test_baseurl_filter.py
r910 r1017 5 5 6 6 7 class Root: 8 def index(self): 9 raise cherrypy.HTTPRedirect('dummy') 10 index.exposed = True 7 def 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 }) 11 20 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 })19 21 20 22 import helper … … 29 31 30 32 if __name__ == '__main__': 33 setup_server() 31 34 helper.testmain() 32 trunk/cherrypy/test/test_cache_filter.py
r906 r1017 6 6 7 7 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 8 def 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 17 18 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 }) 24 25 25 26 … … 35 36 36 37 if __name__ == '__main__': 38 setup_server() 37 39 helper.testmain() 38 40 trunk/cherrypy/test/test_combinedfilters.py
r856 r1017 7 7 europoundUnicode = u'\x80\xa3' 8 8 9 class Root: 10 def index(self): 11 yield u"Hello," 12 yield u"world" 13 yield europoundUnicode 14 index.exposed = True 9 def setup_server(): 10 class Root: 11 def index(self): 12 yield u"Hello," 13 yield u"world" 14 yield europoundUnicode 15 index.exposed = True 15 16 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 }) 23 24 24 25 import helper … … 38 39 39 40 if __name__ == '__main__': 41 setup_server() 40 42 helper.testmain() trunk/cherrypy/test/test_config.py
r1004 r1017 7 7 8 8 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 9 def 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 }) 15 58 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) 22 64 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'}) 29 67 30 cherrypy.tree.mount(Root())31 cherrypy.root.foo = Foo()32 68 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 # 60 70 61 71 import helper … … 65 75 def testConfig(self): 66 76 tests = [ 67 ('*', 'luxuryyacht', 'throatwobblermangrove'),77 ## ('*', 'luxuryyacht', 'throatwobblermangrove'), 68 78 ('/', 'nex', 'None'), 69 79 ('/', 'foo', 'this'), … … 83 93 84 94 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) 90 100 91 101 def testEnvironments(self): … … 105 115 106 116 if __name__ == '__main__': 117 setup_server() 107 118 helper.testmain() trunk/cherrypy/test/test_core.py
r1010 r1017 7 7 from cherrypy.lib import cptools, httptools 8 8 import types 9 9 10 import os 10 11 localDir = 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 12 log_file = os.path.join(localDir, "error.log") 13 log_access_file = os.path.join(localDir, "access.log") 248 14 249 15 defined_http_methods = ("OPTIONS", "GET", "HEAD", "POST", "PUT", "DELETE", 250 16 "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
