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

root/branches/cherrypy-3.0.x/cherrypy/test/modwsgi.py

Revision 1716 (checked in by fumanchu, 1 year ago)

New support for mod_wsgi in the test suite. Use test.py --server=modwsgi.

  • Property svn:eol-style set to native
Line 
1 """Wrapper for mod_wsgi, for use as a CherryPy HTTP server.
2
3 To autostart modwsgi, the "apache" executable or script must be
4 on your system path, or you must override the global APACHE_PATH.
5 On some platforms, "apache" may be called "apachectl" or "apache2ctl"--
6 create a symlink to them if needed.
7
8
9 KNOWN BUGS
10 ==========
11
12 ##1. Apache processes Range headers automatically; CherryPy's truncated
13 ##    output is then truncated again by Apache. See test_core.testRanges.
14 ##    This was worked around in http://www.cherrypy.org/changeset/1319.
15 2. Apache does not allow custom HTTP methods like CONNECT as per the spec.
16     See test_core.testHTTPMethods.
17 3. Max request header and body settings do not work with Apache.
18 ##4. Apache replaces status "reason phrases" automatically. For example,
19 ##    CherryPy may set "304 Not modified" but Apache will write out
20 ##    "304 Not Modified" (capital "M").
21 ##5. Apache does not allow custom error codes as per the spec.
22 ##6. Apache (or perhaps modpython, or modpython_gateway) unquotes %xx in the
23 ##    Request-URI too early.
24 7. mod_wsgi will not read request bodies which use the "chunked"
25     transfer-coding (it passes REQUEST_CHUNKED_ERROR to ap_setup_client_block
26     instead of REQUEST_CHUNKED_DECHUNK, see Apache2's http_protocol.c and
27     mod_python's requestobject.c).
28 8. When responding with 204 No Content, mod_wsgi adds a Content-Length
29     header for you.
30 9. When an error is raised, mod_wsgi has no facility for printing a
31     traceback as the response content (it's sent to the Apache log instead).
32 10. Startup and shutdown of Apache when running mod_wsgi seems slow.
33 """
34
35 import os
36 curdir = os.path.join(os.getcwd(), os.path.dirname(__file__))
37 import re
38 import time
39
40 from cherrypy.test import test
41
42
43 def read_process(cmd, args=""):
44     pipein, pipeout = os.popen4("%s %s" % (cmd, args))
45     try:
46         firstline = pipeout.readline()
47         if (re.search(r"(not recognized|No such file|not found)", firstline,
48                       re.IGNORECASE)):
49             raise IOError('%s must be on your system path.' % cmd)
50         output = firstline + pipeout.read()
51     finally:
52         pipeout.close()
53     return output
54
55
56 APACHE_PATH = "apache"
57 CONF_PATH = "test_mw.conf"
58
59 conf_modwsgi = """
60 # Apache2 server conf file for testing CherryPy with modpython_gateway.
61
62 DocumentRoot "/"
63 Listen %%s
64 LoadModule wsgi_module modules/mod_wsgi.so
65 LoadModule env_module modules/mod_env.so
66
67 WSGIScriptAlias / %s
68 SetEnv testmod %%s
69 """ % os.path.join(curdir, 'modwsgi.py')
70
71
72 def start(testmod, port, conf_template):
73     mpconf = CONF_PATH
74     if not os.path.isabs(mpconf):
75         mpconf = os.path.join(curdir, mpconf)
76    
77     f = open(mpconf, 'wb')
78     try:
79         f.write(conf_template % (port, testmod))
80     finally:
81         f.close()
82    
83     result = read_process(APACHE_PATH, "-k start -f %s" % mpconf)
84     if result:
85         print result
86
87 def stop():
88     """Gracefully shutdown a server that is serving forever."""
89     read_process(APACHE_PATH, "-k stop")
90
91
92 class ModWSGITestHarness(test.TestHarness):
93     """TestHarness for ModWSGI and CherryPy."""
94    
95     use_wsgi = True
96    
97     def _run(self, conf):
98         from cherrypy.test import webtest
99         webtest.WebCase.PORT = self.port
100         webtest.WebCase.harness = self
101         webtest.WebCase.scheme = "http"
102         webtest.WebCase.interactive = self.interactive
103         print
104         print "Running tests:", self.server
105        
106         conf_template = conf_modwsgi
107        
108         # mod_wsgi, since it runs in the Apache process, must be
109         # started separately for each test, and then *that* process
110         # must run the setup_server() function for the test.
111         # Then our process can run the actual test.
112         success = True
113         for testmod in self.tests:
114             try:
115                 start(testmod, self.port, conf_template)
116                 suite = webtest.ReloadingTestLoader().loadTestsFromName(testmod)
117                 result = webtest.TerseTestRunner(verbosity=2).run(suite)
118                 success &= result.wasSuccessful()
119             finally:
120                 stop()
121         if success:
122             return 0
123         else:
124             return 1
125
126
127 loaded = False
128 def application(environ, start_response):
129     import cherrypy
130     global loaded
131     if not loaded:
132         loaded = True
133         modname = "cherrypy.test." + environ['testmod']
134         mod = __import__(modname, globals(), locals(), [''])
135         mod.setup_server()
136        
137         cherrypy.config.update({
138             "log.error_file": os.path.join(curdir, "test.log"),
139             "environment": "test_suite",
140             "engine.SIGHUP": None,
141             "engine.SIGTERM": None,
142             })
143         cherrypy.engine.start(blocking=False)
144     return cherrypy.tree(environ, start_response)
145
Note: See TracBrowser for help on using the browser.

Hosted by WebFaction

Log in as guest/cpguest to create tickets