Package cherrypy :: Package test :: Module modpy
[hide private]
[frames] | no frames]

Source Code for Module cherrypy.test.modpy

  1  """Wrapper for mod_python, for use as a CherryPy HTTP server. 
  2   
  3  To autostart modpython, 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  If you wish to use the WSGI interface instead of our _cpmodpy interface, 
  9  you also need the 'modpython_gateway' module at: 
 10  http://projects.amor.org/misc/wiki/ModPythonGateway 
 11   
 12   
 13  KNOWN BUGS 
 14  ========== 
 15   
 16  1. Apache processes Range headers automatically; CherryPy's truncated 
 17      output is then truncated again by Apache. See test_core.testRanges. 
 18      This was worked around in http://www.cherrypy.org/changeset/1319. 
 19  2. Apache does not allow custom HTTP methods like CONNECT as per the spec. 
 20      See test_core.testHTTPMethods. 
 21  3. Max request header and body settings do not work with Apache. 
 22  4. Apache replaces status "reason phrases" automatically. For example, 
 23      CherryPy may set "304 Not modified" but Apache will write out 
 24      "304 Not Modified" (capital "M"). 
 25  5. Apache does not allow custom error codes as per the spec. 
 26  6. Apache (or perhaps modpython, or modpython_gateway) unquotes %xx in the 
 27      Request-URI too early. 
 28  7. mod_python will not read request bodies which use the "chunked" 
 29      transfer-coding (it passes REQUEST_CHUNKED_ERROR to ap_setup_client_block 
 30      instead of REQUEST_CHUNKED_DECHUNK, see Apache2's http_protocol.c and 
 31      mod_python's requestobject.c). 
 32  """ 
 33   
 34  import os 
 35  curdir = os.path.join(os.getcwd(), os.path.dirname(__file__)) 
 36  import re 
 37  import time 
 38   
 39  from cherrypy.test import test 
 40   
 41   
42 -def read_process(cmd, args=""):
43 pipein, pipeout = os.popen4("%s %s" % (cmd, args)) 44 try: 45 firstline = pipeout.readline() 46 if (re.search(r"(not recognized|No such file|not found)", firstline, 47 re.IGNORECASE)): 48 raise IOError('%s must be on your system path.' % cmd) 49 output = firstline + pipeout.read() 50 finally: 51 pipeout.close() 52 return output
53 54 55 APACHE_PATH = "apache" 56 CONF_PATH = "test_mp.conf" 57 58 conf_modpython_gateway = """ 59 # Apache2 server conf file for testing CherryPy with modpython_gateway. 60 61 DocumentRoot "/" 62 Listen %s 63 LoadModule python_module modules/mod_python.so 64 65 SetHandler python-program 66 PythonFixupHandler cherrypy.test.modpy::wsgisetup 67 PythonOption testmod %s 68 PythonHandler modpython_gateway::handler 69 PythonOption wsgi.application cherrypy::tree 70 PythonDebug On 71 """ 72 73 conf_cpmodpy = """ 74 # Apache2 server conf file for testing CherryPy with _cpmodpy. 75 76 DocumentRoot "/" 77 Listen %s 78 LoadModule python_module modules/mod_python.so 79 80 SetHandler python-program 81 PythonHandler cherrypy._cpmodpy::handler 82 PythonOption cherrypy.setup cherrypy.test.%s::setup_server 83 PythonDebug On 84 """ 85
86 -def start(testmod, port, conf_template):
87 mpconf = CONF_PATH 88 if not os.path.isabs(mpconf): 89 mpconf = os.path.join(curdir, mpconf) 90 91 f = open(mpconf, 'wb') 92 try: 93 f.write(conf_template % (port, testmod)) 94 finally: 95 f.close() 96 97 result = read_process(APACHE_PATH, "-k start -f %s" % mpconf) 98 if result: 99 print result
100
101 -def stop():
102 """Gracefully shutdown a server that is serving forever.""" 103 read_process(APACHE_PATH, "-k stop")
104 105 106 loaded = False
107 -def wsgisetup(req):
108 global loaded 109 if not loaded: 110 loaded = True 111 options = req.get_options() 112 modname = options['testmod'] 113 mod = __import__(modname, globals(), locals(), ['']) 114 mod.setup_server() 115 116 import cherrypy 117 cherrypy.config.update({ 118 "log.error_file": os.path.join(curdir, "test.log"), 119 "environment": "production", 120 }) 121 cherrypy.engine.start(blocking=False) 122 from mod_python import apache 123 return apache.OK
124 125
126 -class ModPythonTestHarness(test.TestHarness):
127 """TestHarness for ModPython and CherryPy.""" 128 129 use_wsgi = False 130
131 - def _run(self, conf):
132 from cherrypy.test import webtest 133 webtest.WebCase.PORT = self.port 134 webtest.WebCase.harness = self 135 webtest.WebCase.scheme = "http" 136 webtest.WebCase.interactive = self.interactive 137 print 138 print "Running tests:", self.server 139 140 if self.use_wsgi: 141 conf_template = conf_modpython_gateway 142 else: 143 conf_template = conf_cpmodpy 144 145 # mod_python, since it runs in the Apache process, must be 146 # started separately for each test, and then *that* process 147 # must run the setup_server() function for the test. 148 # Then our process can run the actual test. 149 success = True 150 for testmod in self.tests: 151 try: 152 start(testmod, self.port, conf_template) 153 suite = webtest.ReloadingTestLoader().loadTestsFromName(testmod) 154 result = webtest.TerseTestRunner(verbosity=2).run(suite) 155 success &= result.wasSuccessful() 156 finally: 157 stop() 158 if success: 159 return 0 160 else: 161 return 1
162