You are viewing a plain text version of this content. The canonical link for it is here.
Posted to mod_python-commits@quetz.apache.org by gr...@apache.org on 2002/09/24 18:01:28 UTC
cvs commit: httpd-python/test/htdocs tests.py
grisha 2002/09/24 09:01:28
Modified: Doc modpython4.tex
src filterobject.c mod_python.c requestobject.c util.c
test test.py
test/conf test.conf.tmpl
test/htdocs tests.py
Log:
More thorough tests, especially request object, also a few fixes.
Revision Changes Path
1.25 +16 -9 httpd-python/Doc/modpython4.tex
Index: modpython4.tex
===================================================================
RCS file: /home/cvs/httpd-python/Doc/modpython4.tex,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -r1.24 -r1.25
--- modpython4.tex 19 Sep 2002 20:11:35 -0000 1.24
+++ modpython4.tex 24 Sep 2002 16:01:28 -0000 1.25
@@ -318,7 +318,9 @@
\var{server} is a reference to a \member{req.server} object. If
\var{server} is not specified, then the error will be logged to the
default error log, otherwise it will be written to the error log for
-the appropriate virtual server.
+the appropriate virtual server. When \var{server} is not specified,
+the setting of LogLevel does not apply, the LogLevel is dictated by
+an httpd compile-time default, usually \code{warn}.
If you have a reference to a request object available, consider using
\method{req.log_error} intead, it will prepend request-specific
@@ -366,7 +368,8 @@
\begin{funcdesc}{config_tree}{}
Returns the server-level configuration tree. This tree does not
-include directives from .htaccess files.
+include directives from .htaccess files. This is a \emph{copy} of
+the tree, modifying it has no effect on the actual configuration.
\end{funcdesc}
\begin{funcdesc}{server_root}{}
@@ -483,6 +486,10 @@
the list of methods is first cleared.
\end{methoddesc}
+\begin{methoddesc}[request]{document_root}{}
+Returns DocumentRoot setting.
+\end{methoddesc}
+
\begin{methoddesc}[request]{get_basic_auth_pw}{}
Returns a string containing the password when Basic authentication is
used.
@@ -614,6 +621,13 @@
Writes \var{string} directly to the client, then flushes the buffer.
\end{methoddesc}
+\begin{methoddesc}[request]{set_content_length}{len}
+Sets the value of \member{req.clength} and the "Conent-Length" header
+to len. Note that after the headers have been sent out (which happens
+just before the first byte of the body is written, i.e. first call to
+\member{req.write()}), calling the method is meaningless.
+\end{methoddesc}
+
\subsubsection{Request Members\label{pyapi-mprequest-mem}}
\begin{memberdesc}[request]{connection}
@@ -821,13 +835,6 @@
\begin{memberdesc}[request]{interpreter}
The name of the subinterpreter under which we're running.
\emph{(Read-Only)}
-\end{memberdesc}
-
-\begin{memberdesc}[request]{notes}
-A \code{table} object that could be used to store miscellaneous
-general purpose info that lives for as long as the request lives. If
-you need to pass data between handlers, it's better to simply add
-members to the request object than to use \member{notes}.
\end{memberdesc}
\begin{memberdesc}[request]{content_type}
1.14 +14 -19 httpd-python/src/filterobject.c
Index: filterobject.c
===================================================================
RCS file: /home/cvs/httpd-python/src/filterobject.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- filterobject.c 17 Sep 2002 03:37:23 -0000 1.13
+++ filterobject.c 24 Sep 2002 16:01:28 -0000 1.14
@@ -104,7 +104,6 @@
result->closed = 0;
result->softspace = 0;
- result->bytes_written = 0;
result->handler = handler;
result->dir = dir;
@@ -346,7 +345,6 @@
c->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(self->bb_out, b);
- self->bytes_written += len;
}
Py_INCREF(Py_None);
@@ -401,24 +399,21 @@
if (! self->closed) {
- if (self->bytes_written) {
-
- /* does the output brigade exist? */
- if (!self->bb_out) {
- self->bb_out = apr_brigade_create(self->f->r->pool,
- c->bucket_alloc);
- }
+ /* does the output brigade exist? */
+ if (!self->bb_out) {
+ self->bb_out = apr_brigade_create(self->f->r->pool,
+ c->bucket_alloc);
+ }
- APR_BRIGADE_INSERT_TAIL(self->bb_out,
- apr_bucket_eos_create(c->bucket_alloc));
+ APR_BRIGADE_INSERT_TAIL(self->bb_out,
+ apr_bucket_eos_create(c->bucket_alloc));
- if (! self->is_input) {
- Py_BEGIN_ALLOW_THREADS;
- ap_pass_brigade(self->f->next, self->bb_out);
- Py_END_ALLOW_THREADS;
- self->bb_out = NULL;
- }
- }
+ if (! self->is_input) {
+ Py_BEGIN_ALLOW_THREADS;
+ ap_pass_brigade(self->f->next, self->bb_out);
+ Py_END_ALLOW_THREADS;
+ self->bb_out = NULL;
+ }
self->closed = 1;
}
1.78 +10 -8 httpd-python/src/mod_python.c
Index: mod_python.c
===================================================================
RCS file: /home/cvs/httpd-python/src/mod_python.c,v
retrieving revision 1.77
retrieving revision 1.78
diff -u -r1.77 -r1.78
--- mod_python.c 18 Sep 2002 20:13:37 -0000 1.77
+++ mod_python.c 24 Sep 2002 16:01:28 -0000 1.78
@@ -1135,6 +1135,7 @@
/* create filter */
filter = (filterobject *)MpFilter_FromFilter(f, bb, is_input, mode, readbytes,
fh->handler, fh->dir);
+
Py_INCREF(request_obj);
filter->request_obj = request_obj;
@@ -1501,7 +1502,7 @@
/* register the filter NOTE - this only works so long as the
directive is only allowed in the main config. For .htaccess we
would have to make sure not to duplicate this */
- ap_register_input_filter(name, python_input_filter, NULL, AP_FTYPE_CONNECTION);
+ frec = ap_register_input_filter(name, python_input_filter, NULL, AP_FTYPE_CONNECTION);
conf = (py_config *) mconfig;
@@ -1518,23 +1519,24 @@
const char *handler, const char *name) {
py_config *conf;
py_handler *fh;
+ ap_filter_rec_t *frec;
if (!name)
name = apr_pstrdup(cmd->pool, handler);
+ /* register the filter NOTE - this only works so long as the
+ directive is only allowed in the main config. For .htaccess we
+ would have to make sure not to duplicate this */
+ frec = ap_register_output_filter(name, python_output_filter, NULL, AP_FTYPE_RESOURCE);
+
conf = (py_config *) mconfig;
fh = (py_handler *) apr_pcalloc(cmd->pool, sizeof(py_handler));
fh->handler = (char *)handler;
fh->dir = conf->config_dir;
- apr_hash_set(conf->out_filters, name, APR_HASH_KEY_STRING, fh);
+ apr_hash_set(conf->out_filters, frec->name, APR_HASH_KEY_STRING, fh);
- /* register the filter NOTE - this only works so long as the
- directive is only allowed in the main config. For .htaccess we
- would have to make sure not to duplicate this */
- ap_register_output_filter(name, python_output_filter, NULL, AP_FTYPE_RESOURCE);
-
return NULL;
}
1.32 +52 -4 httpd-python/src/requestobject.c
Index: requestobject.c
===================================================================
RCS file: /home/cvs/httpd-python/src/requestobject.c,v
retrieving revision 1.31
retrieving revision 1.32
diff -u -r1.31 -r1.32
--- requestobject.c 15 Sep 2002 23:45:35 -0000 1.31
+++ requestobject.c 24 Sep 2002 16:01:28 -0000 1.32
@@ -756,6 +756,26 @@
static PyObject * req_send_http_header(requestobject *self)
{
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+/**
+ ** request.set_content_length(request self, long content_length)
+ **
+ * write output to the client
+ */
+
+static PyObject * req_set_content_length(requestobject *self, PyObject *args)
+{
+ long len;
+
+ if (! PyArg_ParseTuple(args, "l", &len))
+ return NULL; /* bad args */
+
+ ap_set_content_length(self->request_rec, len);
+
+ Py_INCREF(Py_None);
return Py_None;
}
@@ -788,7 +808,20 @@
}
+//XXX segfault generator
+static char* req_segfault(requestobject *self)
+{
+
+ char *x = 1;
+
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, self->request_rec, "about to segfault...");
+
+ *x = 'x';
+ return x;
+}
+
static PyMethodDef request_methods[] = {
+ {"segfault", (PyCFunction) req_segfault, METH_NOARGS},
{"add_common_vars", (PyCFunction) req_add_common_vars, METH_NOARGS},
{"add_handler", (PyCFunction) req_add_handler, METH_VARARGS},
{"allow_methods", (PyCFunction) req_allow_methods, METH_VARARGS},
@@ -805,6 +838,7 @@
{"readlines", (PyCFunction) req_readlines, METH_VARARGS},
{"register_cleanup", (PyCFunction) req_register_cleanup, METH_VARARGS},
{"send_http_header", (PyCFunction) req_send_http_header, METH_NOARGS},
+ {"set_content_length", (PyCFunction) req_set_content_length, METH_VARARGS},
{"write", (PyCFunction) req_write, METH_VARARGS},
{ NULL, NULL } /* sentinel */
};
@@ -967,6 +1001,20 @@
}
/**
+ ** getreq_recmbr_time
+ **
+ * Retrieves apr_time_t request_rec members
+ */
+
+static PyObject *getreq_recmbr_time(requestobject *self, void *name)
+{
+ PyMemberDef *md = find_memberdef(request_rec_mbrs, name);
+ char *addr = (char *)self->request_rec + md->offset;
+ apr_time_t time = *(apr_time_t*)addr;
+ return PyFloat_FromDouble(time*0.000001);
+}
+
+/**
** getreq_rec_ah
**
* For array headers that will get converted to tuple
@@ -974,7 +1022,7 @@
static PyObject *getreq_rec_ah(requestobject *self, void *name)
{
- const PyMemberDef *md = find_memberdef(request_rec_mbrs, (char*)name);
+ const PyMemberDef *md = find_memberdef(request_rec_mbrs, name);
apr_array_header_t *ah =
(apr_array_header_t *)((void *)self->request_rec + md->offset);
@@ -1038,7 +1086,7 @@
{"protocol", (getter)getreq_recmbr, NULL, "Protocol as given to us, or HTTP/0.9", "protocol"},
{"proto_num", (getter)getreq_recmbr, NULL, "Protocol version. 1.1 = 1001", "proto_num"},
{"hostname", (getter)getreq_recmbr, NULL, "Host, as set by full URI or Host:", "hostname"},
- {"request_time", (getter)getreq_recmbr, NULL, "When request started", "request_time"},
+ {"request_time", (getter)getreq_recmbr_time, NULL, "When request started", "request_time"},
{"status_line", (getter)getreq_recmbr, NULL, "Status line, if set by script", "status_line"},
{"status", (getter)getreq_recmbr, (setter)setreq_recmbr, "Status", "status"},
{"method", (getter)getreq_recmbr, NULL, "Request method", "method"},
@@ -1048,7 +1096,7 @@
{"allowed_methods", (getter)getreq_rec_ml, NULL, "Allowed methods", "allowed_methods"},
{"sent_bodyct", (getter)getreq_recmbr, NULL, "Byte count in stream for body", "sent_boduct"},
{"bytes_sent", (getter)getreq_recmbr, NULL, "Bytes sent", "bytes_sent"},
- {"mtime", (getter)getreq_recmbr, NULL, "Time resource was last modified", "mtime"},
+ {"mtime", (getter)getreq_recmbr_time, NULL, "Time resource was last modified", "mtime"},
{"chunked", (getter)getreq_recmbr, NULL, "Sending chunked transfer-coding", "chunked"},
{"boundary", (getter)getreq_recmbr, NULL, "Multipart/byteranges boundary", "boundary"},
{"range", (getter)getreq_recmbr, NULL, "The Range: header", "range"},
1.12 +4 -4 httpd-python/src/util.c
Index: util.c
===================================================================
RCS file: /home/cvs/httpd-python/src/util.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- util.c 19 Sep 2002 20:11:35 -0000 1.11
+++ util.c 24 Sep 2002 16:01:28 -0000 1.12
@@ -186,19 +186,19 @@
PyTuple_SET_ITEM(t, 6, Py_None);
}
if (f->valid & APR_FINFO_ATIME) {
- PyTuple_SET_ITEM(t, 7, PyInt_FromLong(f->atime/1000000));
+ PyTuple_SET_ITEM(t, 7, PyInt_FromLong(f->atime*0.000001));
} else {
Py_INCREF(Py_None);
PyTuple_SET_ITEM(t, 7, Py_None);
}
if (f->valid & APR_FINFO_MTIME) {
- PyTuple_SET_ITEM(t, 8, PyInt_FromLong(f->mtime/1000000));
+ PyTuple_SET_ITEM(t, 8, PyInt_FromLong(f->mtime*0.000001));
} else {
Py_INCREF(Py_None);
PyTuple_SET_ITEM(t, 8, Py_None);
}
if (f->valid & APR_FINFO_CTIME) {
- PyTuple_SET_ITEM(t, 9, PyInt_FromLong(f->ctime/10000000));
+ PyTuple_SET_ITEM(t, 9, PyInt_FromLong(f->ctime*0.000001));
} else {
Py_INCREF(Py_None);
PyTuple_SET_ITEM(t, 9, Py_None);
1.11 +46 -60 httpd-python/test/test.py
Index: test.py
===================================================================
RCS file: /home/cvs/httpd-python/test/test.py,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- test.py 6 Sep 2002 22:06:29 -0000 1.10
+++ test.py 24 Sep 2002 16:01:28 -0000 1.11
@@ -16,6 +16,13 @@
import commands
import urllib
+
+# need to incorporate the gdb into the testing process....
+# httpd needs to be invoked under gdb [make optional], and
+# the url fetching should be forked.
+# what's the deal with gdb's being different?
+
+
def findUnusedPort():
# bind to port 0 which makes the OS find the next
@@ -53,6 +60,11 @@
f.write("\n# --APPENDED-- \n\n"+append)
f.close()
+ def makeGdbFile(file):
+ f = open(file, "w")
+ f.write("run -f %s -X" % PARAMS("config"))
+ f.close()
+
def startApache(self):
print " Starting Apache...."
@@ -60,12 +72,17 @@
cmd = '%s -f %s' % (HTTPD, PARAMS["config"])
print " ", cmd
print commands.getoutput(cmd)
+ self.apache_running = 1
- def tearDown(self):
-
+ def stopApache(self):
print " Stopping Apache..."
pid = commands.getoutput("cat %s/logs/httpd.pid" % PARAMS["server_root"])
commands.getoutput("kill "+pid)
+ self.apache_running = 0
+
+ def tearDown(self):
+ if self.apache_running:
+ self.stopApache()
def testLoadModule(self):
@@ -237,7 +254,6 @@
" SetHandler python-program\n" + \
" PythonHandler tests::req_document_root\n" + \
" PythonDebug On\n" + \
- " PythonOption secret sauce\n" + \
"</Directory>\n"
self.makeConfig(cfg)
@@ -254,56 +270,6 @@
if (rsp != PARAMS["document_root"]):
self.fail("test failed")
- def test_req_get_config(self):
-
- print "\n* Testing req.get_config() and get_options()"
-
- cfg = "<Directory %s/htdocs>\n" % PARAMS["server_root"]+ \
- " SetHandler python-program\n" + \
- " PythonHandler tests::req_get_config\n" + \
- " PythonDebug On\n" + \
- " PythonOption secret sauce\n" + \
- "</Directory>\n"
-
- self.makeConfig(cfg)
- self.startApache()
-
- url = "http://127.0.0.1:%s/tests.py" % PARAMS["port"]
- print " url: "+url
-
- f = urllib.urlopen(url)
- rsp = f.read()
- f.close()
- print " response: "+rsp
-
- if (rsp != "test ok"):
- self.fail("test failed")
-
- def test_req_get_remote_host(self):
-
- print "\n* Testing req.get_remote_host()"
-
- cfg = "<Directory %s/htdocs>\n" % PARAMS["server_root"]+ \
- " SetHandler python-program\n" + \
- " PythonHandler tests::req_get_remote_host\n" + \
- " PythonDebug On\n" + \
- "</Directory>\n" + \
- "HostNameLookups Off\n"
-
- self.makeConfig(cfg)
- self.startApache()
-
- url = "http://127.0.0.1:%s/tests.py" % PARAMS["port"]
- print " url: "+url
-
- f = urllib.urlopen(url)
- rsp = f.read()
- f.close()
- print " response: "+rsp
-
- if (rsp != "test ok"):
- self.fail("test failed")
-
def test_req_internal_redirect(self):
print "\n* Testing req.internal_redirect()"
@@ -535,9 +501,9 @@
cfg = " SetHandler python-program\n" + \
" PythonPath ['%s']+sys.path\n" % PARAMS["document_root"] + \
" PythonHandler tests::simplehandler\n" + \
- " PythonOutputFilter tests::outputfilter myfilter\n" + \
+ " PythonOutputFilter tests::outputfilter MP_TEST_FILTER\n" + \
" PythonDebug On\n" + \
- " AddOutputFilter myfilter .py\n"
+ " AddOutputFilter MP_TEST_FILTER .py\n"
self.makeConfig(cfg)
self.startApache()
@@ -575,19 +541,39 @@
if (rsp != "test ok"):
self.fail("test failed")
+ def test_internal(self):
+
+ print "\n* Testing internally"
+
+ cfg = " SetHandler python-program\n" + \
+ " PythonPath ['%s']+sys.path\n" % PARAMS["document_root"] + \
+ " PythonHandler tests\n" + \
+ " PythonOption testing 123\n" + \
+ " PythonDebug On\n"
+
+ self.makeConfig(cfg)
+ self.startApache()
+
+ url = "http://127.0.0.1:%s/tests.py" % PARAMS["port"]
+ print " url: "+url
+
+ f = urllib.urlopen(url)
+ rsp = f.read()
+ f.close()
+ print " response: ", rsp
+
+ if (rsp[-7:] != "test ok"):
+ self.fail("Some tests failed, see error_log")
+
def suite():
mpTestSuite = unittest.TestSuite()
mpTestSuite.addTest(ModPythonTestCase("testLoadModule"))
- mpTestSuite.addTest(ModPythonTestCase("test_apache_log_error"))
- mpTestSuite.addTest(ModPythonTestCase("test_apache_table"))
- mpTestSuite.addTest(ModPythonTestCase("test_req_add_common_vars"))
+ mpTestSuite.addTest(ModPythonTestCase("test_internal"))
mpTestSuite.addTest(ModPythonTestCase("test_req_add_handler"))
mpTestSuite.addTest(ModPythonTestCase("test_req_allow_methods"))
mpTestSuite.addTest(ModPythonTestCase("test_req_document_root"))
mpTestSuite.addTest(ModPythonTestCase("test_req_get_basic_auth_pw"))
- mpTestSuite.addTest(ModPythonTestCase("test_req_get_config"))
- mpTestSuite.addTest(ModPythonTestCase("test_req_get_remote_host"))
mpTestSuite.addTest(ModPythonTestCase("test_req_internal_redirect"))
mpTestSuite.addTest(ModPythonTestCase("test_req_read"))
mpTestSuite.addTest(ModPythonTestCase("test_req_readline"))
1.2 +1 -0 httpd-python/test/conf/test.conf.tmpl
Index: test.conf.tmpl
===================================================================
RCS file: /home/cvs/httpd-python/test/conf/test.conf.tmpl,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- test.conf.tmpl 18 Aug 2002 18:43:36 -0000 1.1
+++ test.conf.tmpl 24 Sep 2002 16:01:28 -0000 1.2
@@ -25,6 +25,7 @@
ServerRoot "%(server_root)s"
ErrorLog "logs/error_log"
+LogLevel debug
TypesConfig "conf/mime.types"
PidFile "logs/httpd.pid"
1.9 +352 -51 httpd-python/test/htdocs/tests.py
Index: tests.py
===================================================================
RCS file: /home/cvs/httpd-python/test/htdocs/tests.py,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- tests.py 6 Sep 2002 22:06:29 -0000 1.8
+++ tests.py 24 Sep 2002 16:01:28 -0000 1.9
@@ -2,43 +2,355 @@
# mod_python tests
from mod_python import apache
+import unittest
+import re
+import time
+import os
+
+class InternalTestCase(unittest.TestCase):
+
+ def __init__(self, methodName, req):
+ unittest.TestCase.__init__(self, methodName)
+ self.req = req
+
+ def test_apache_log_error(self):
+
+ s = self.req.server
+ apache.log_error("Testing apache.log_error():", apache.APLOG_INFO, s)
+ apache.log_error("xEMERGx", apache.APLOG_EMERG, s)
+ apache.log_error("xALERTx", apache.APLOG_ALERT, s)
+ apache.log_error("xCRITx", apache.APLOG_CRIT, s)
+ apache.log_error("xERRx", apache.APLOG_ERR, s)
+ apache.log_error("xWARNINGx", apache.APLOG_WARNING, s)
+ apache.log_error("xNOTICEx", apache.APLOG_NOTICE, s)
+ apache.log_error("xINFOx", apache.APLOG_INFO, s)
+ apache.log_error("xDEBUGx", apache.APLOG_DEBUG, s)
+
+ # see what's in the log now
+ f = open("%s/logs/error_log" % apache.server_root())
+ # for some reason re doesn't like \n, why?
+ import string
+ log = "".join(map(string.strip, f.readlines()))
+ f.close()
+
+ if not re.search("xEMERGx.*xALERTx.*xCRITx.*xERRx.*xWARNINGx.*xNOTICEx.*xINFOx.*xDEBUGx", log):
+ self.fail("Could not find test messages in error_log")
+
+
+ def test_apache_table(self):
+
+ self.req.log_error("Testing table object.")
+
+ # tests borrowed from Python test quite for dict
+ _test_table()
+
+ # inheritance
+ class mytable(apache.table):
+ def __str__(self):
+ return "str() from mytable"
+ mt = mytable({'a':'b'})
+
+ # add()
+ a = apache.table({'a':'b'})
+ a.add('a', 'c')
+ if a['a'] != ['b', 'c']:
+ self.fail('table.add() broken: a["a"] is %s' % `a["a"]`)
+
+ def test_req_add_common_vars(self):
+
+ self.req.log_error("Testing req.add_common_vars().")
+
+ a = len(self.req.subprocess_env)
+ self.req.add_common_vars()
+ b = len(self.req.subprocess_env)
+ if a >= b:
+ self.fail("req.subprocess_env() is same size before and after")
+
+ def test_req_members(self):
+
+ # just run through request members making sure
+ # they make sense
+
+ req = self.req
+ log = req.log_error
+ log("Examining request memebers:")
+
+ log(" req.connection: %s" % `req.connection`)
+ s = str(type(req.connection))
+ if s != "<type 'mp_conn'>":
+ self.fail("strange req.connection type %s" % `s`)
+
+ log(" req.server: '%s'" % `req.server`)
+ s = str(type(req.server))
+ if s != "<type 'mp_server'>":
+ self.fail("strange req.server type %s" % `s`)
+
+ for x in ((req.next, "next"),
+ (req.prev, "prev"),
+ (req.main, "main")):
+ val, name = x
+ log(" req.%s: '%s'" % (name, `val`))
+ if val:
+ self.fail("strange, req.%s should be None, not %s" % (name, `val`))
+
+ log(" req.the_request: '%s'" % req.the_request)
+ if not re.match(r"GET /.* HTTP/1\.", req.the_request):
+ self.fail("strange req.the_request %s" % `req.the_request`)
+
+ for x in ((req.assbackwards, "assbackwards"),
+ (req.proxyreq, "proxyreq"),
+ (req.header_only, "header_only")):
+ val, name = x
+ log(" req.%s: %s" % (name, `val`))
+ if val:
+ self.fail("%s should be 0" % name)
+
+ log(" req.protocol: %s" % `req.protocol`)
+ if not req.protocol == req.the_request.split()[-1]:
+ self.fail("req.protocol doesn't match req.the_request")
+
+ log(" req.proto_num: %s" % `req.proto_num`)
+ if req.proto_num != 1000 + int(req.protocol[-1]):
+ self.fail("req.proto_num doesn't match req.protocol")
+
+ log(" req.hostname: %s" % `req.hostname`)
+ if req.hostname != "127.0.0.1":
+ self.fail("req.hostname isn't '127.0.0.1'")
+
+ log(" req.request_time: %s" % `req.request_time`)
+ if (time.time() - req.request_time) > 2:
+ self.fail("req.request_time suggests request started more than 2 secs ago")
+
+ log(" req.status_line: %s" % `req.status_line`)
+ if req.status_line:
+ self.fail("req.status_line should be None at this point")
+
+ log(" req.status: %s" % `req.status`)
+ if req.status != 200:
+ self.fail("req.status should be 200")
+ req.status = req.status # make sure its writable
+
+ log(" req.method: %s" % `req.method`)
+ if req.method != "GET":
+ self.fail("req.method should be 'GET'")
+
+ log(" req.method_number: %s" % `req.method_number`)
+ if req.method_number != 0:
+ self.fail("req.method_number should be 0")
+
+ log(" req.allowed: %s" % `req.allowed`)
+ if req.allowed != 0:
+ self.fail("req.allowed should be 0")
+
+ log(" req.allowed_xmethods: %s" % `req.allowed_xmethods`)
+ if req.allowed_xmethods != ():
+ self.fail("req.allowed_xmethods should be an empty tuple")
+
+ log(" req.allowed_methods: %s" % `req.allowed_methods`)
+ if req.allowed_methods:
+ self.fail("req.allowed_methods should be None")
+
+ log(" req.sent_bodyct: %s" % `req.sent_bodyct`)
+ if req.sent_bodyct != 0:
+ self.fail("req.sent_bodyct should be 0")
+
+ log(" req.bytes_sent: %s" % `req.bytes_sent`)
+ save = req.bytes_sent
+ log(" writing 4 bytes...")
+ req.write("1234")
+ log(" req.bytes_sent: %s" % `req.bytes_sent`)
+ if req.bytes_sent - save != 4:
+ self.fail("req.bytes_sent should have incremented by 4, but didn't")
+
+ log(" req.mtime: %s" % `req.mtime`)
+ if req.mtime != 0:
+ self.fail("req.mtime should be 0")
+
+ log(" req.chunked: %s" % `req.chunked`)
+ if req.chunked != 0:
+ self.fail("req.chunked should be 0")
+
+ log(" req.range: %s" % `req.range`)
+ if req.range:
+ self.fail("req.range should be None")
+
+ log(" req.clength: %s" % `req.clength`)
+ log(" calling req.set_content_length(15)...")
+ req.set_content_length(15)
+ log(" req.clength: %s" % `req.clength`)
+ if req.clength != 15:
+ self.fail("req.clength should be 15")
+
+ log(" req.remaining: %s" % `req.remaining`)
+ if req.remaining != 0:
+ self.fail("req.remaining should be 0")
+
+ log(" req.read_length: %s" % `req.read_length`)
+ if req.read_length != 0:
+ self.fail("req.read_length should be 0")
+
+ log(" req.read_body: %s" % `req.read_body`)
+ if req.read_body != 0:
+ self.fail("req.read_body should be 0")
+
+ log(" req.read_chunked: %s" % `req.read_chunked`)
+ if req.read_chunked != 0:
+ self.fail("req.read_chunked should be 0")
+
+ log(" req.expecting_100: %s" % `req.expecting_100`)
+ if req.expecting_100 != 0:
+ self.fail("req.expecting_100 should be 0")
+
+ log(" req.headers_int: %s" % `req.headers_in`)
+ if req.headers_in["User-agent"][:13].lower() != "python-urllib":
+ self.fail("The 'user-agnet' header should begin with 'Python-urllib'")
+
+ log(" req.headers_out: %s" % `req.headers_out`)
+ if ((not req.headers_out.has_key("content-length")) or
+ req.headers_out["content-length"] != "15"):
+ self.fail("req.headers_out['content-length'] should be 15")
+
+ log(" req.subprocess_env: %s" % `req.subprocess_env`)
+ if req.subprocess_env["SERVER_SOFTWARE"].find("Python") == -1:
+ self.fail("req.subprocess_env['SERVER_SOFTWARE'] should contain 'Python'")
+
+ log(" req.notes: %s" % `req.notes`)
+ log(" doing req.notes['testing'] = '123' ...")
+ req.notes['testing'] = '123'
+ log(" req.notes: %s" % `req.notes`)
+ if req.notes["testing"] != '123':
+ self.fail("req.notes['testing'] should be '123'")
+
+ log(" req.phase: %s" % `req.phase`)
+ if req.phase != "PythonHandler":
+ self.fail("req.phase should be 'PythonHandler'")
+
+ log(" req.interpreter: %s" % `req.interpreter`)
+ if req.interpreter != req.server.server_hostname:
+ self.fail("req.interpreter should be same as req.server_hostname: %s" % `req.server_hostname`)
+
+ log(" req.content_type: %s" % `req.content_type`)
+ log(" doing req.content_type = 'test/123' ...")
+ req.content_type = 'test/123'
+ log(" req.content_type: %s" % `req.content_type`)
+ if req.content_type != 'test/123' or not req._content_type_set:
+ self.fail("req.content_type should be 'test/123' and req._content_type_set 1")
+
+ log(" req.handler: %s" % `req.handler`)
+ if req.handler != "python-program":
+ self.fail("req.handler should be 'python-program'")
+
+ log(" req.content_encoding: %s" % `req.content_encoding`)
+ if req.content_encoding:
+ self.fail("req.content_encoding should be None")
+
+ log(" req.vlist_validator: %s" % `req.vlist_validator`)
+ if req.vlist_validator:
+ self.fail("req.vlist_validator should be None")
+
+ log(" req.user: %s" % `req.user`)
+ if req.user:
+ self.fail("req.user should be None")
+
+ log(" req.ap_auth_type: %s" % `req.ap_auth_type`)
+ if req.ap_auth_type:
+ self.fail("req.ap_auth_type should be None")
+
+ log(" req.no_cache: %s" % `req.no_cache`)
+ if req.no_cache != 0:
+ self.fail("req.no_cache should be 0")
+
+ log(" req.no_local_copy: %s" % `req.no_local_copy`)
+ if req.no_local_copy != 0:
+ self.fail("req.no_local_copy should be 0")
+
+ log(" req.unparsed_uri: %s" % `req.unparsed_uri`)
+ if req.unparsed_uri != "/tests.py":
+ self.fail("req.unparse_uri should be '/tests.py'")
+
+ log(" req.uri: %s" % `req.uri`)
+ if req.uri != "/tests.py":
+ self.fail("req.uri should be '/tests.py'")
+
+ log(" req.filename: %s" % `req.filename`)
+ if req.filename != req.document_root() + req.uri:
+ self.fail("req.filename should be req.document_root() + req.uri, but it isn't")
+
+ log(" req.canonical_filename: %s" % `req.canonical_filename`)
+ if not req.canonical_filename:
+ self.fail("req.canonical_filename should not be blank")
+
+ log(" req.path_info: %s" % `req.path_info`)
+ if req.path_info != '':
+ self.fail("req.path_info should be ''")
+
+ log(" req.args: %s" % `req.args`)
+ if req.args:
+ self.fail("req.args should be None")
+
+ log(" req.finfo: %s" % `req.finfo`)
+ if req.finfo[10] != req.canonical_filename:
+ self.fail("req.finfo[10] should be the (canonical) filename")
+
+ log(" req.parsed_uri: %s" % `req.parsed_uri`)
+ if req.parsed_uri[6] != '/tests.py':
+ self.fail("req.parsed_uri[6] should be '/tests.py'")
+
+ log(" req.used_path_info: %s" % `req.used_path_info`)
+ if req.used_path_info != 2:
+ self.fail("req.used_path_info should be 2") # XXX really? :-)
+
+ log(" req.eos_sent: %s" % `req.eos_sent`)
+ if req.eos_sent:
+ self.fail("req.eos_sent says we sent EOS, but we didn't")
+
+ def test_req_get_config(self):
+
+ req = self.req
+ log = req.log_error
+
+ log("req.get_config(): %s" % `req.get_config()`)
+ if req.get_config()["PythonDebug"] != "1":
+ self.fail("get_config return should show PythonDebug 1")
+
+ log("req.get_options(): %s" % `req.get_options()`)
+ if req.get_options() != apache.table({"testing":"123"}):
+ self.fail("get_options() should contain 'testing':'123'")
+
+ def test_req_get_remote_host(self):
+
+ # simulating this test for real is too complex...
+ req = self.req
+ log = req.log_error
+ log("req.get_get_remote_host(): %s" % `req.get_remote_host(apache.REMOTE_HOST)`)
+ log("req.get_get_remote_host(): %s" % `req.get_remote_host()`)
+ if (req.get_remote_host(apache.REMOTE_HOST) != None) or \
+ (req.get_remote_host() != "127.0.0.1"):
+ self.fail("remote host test failed")
+
+
+def make_suite(req):
+
+ mpTestSuite = unittest.TestSuite()
+ mpTestSuite.addTest(InternalTestCase("test_apache_log_error", req))
+ mpTestSuite.addTest(InternalTestCase("test_apache_table", req))
+ mpTestSuite.addTest(InternalTestCase("test_req_add_common_vars", req))
+ mpTestSuite.addTest(InternalTestCase("test_req_members", req))
+ mpTestSuite.addTest(InternalTestCase("test_req_get_config", req))
+ mpTestSuite.addTest(InternalTestCase("test_req_get_remote_host", req))
+ return mpTestSuite
-TestFailed = "TestFailed"
-
-def apache_log_error(req):
-
- apache.log_error("This is a test message")
- req.write("Just wrote something to log\n")
-
- return apache.OK
-
-def apache_table(req):
-
- # tests borrowed from Python test quite for dict
- _test_table()
-
- # inheritance
- class mytable(apache.table):
- def __str__(self):
- return "str() from mytable"
- mt = mytable({'a':'b'})
- # add()
- a = apache.table({'a':'b'})
- a.add('a', 'c')
- if a['a'] != ['b', 'c']: raise TestFailed, 'table.add() broken: a["a"] is %s' % `a["a"]`
+def handler(req):
- req.write("test ok")
- return apache.OK
+ tr = unittest.TextTestRunner()
+ result = tr.run(make_suite(req))
-def req_add_common_vars(req):
+ if result.wasSuccessful():
+ req.write("test ok")
+ else:
+ req.write("test failed")
- a = len(req.subprocess_env)
- req.add_common_vars()
- b = len(req.subprocess_env)
- if a >= b: raise TestFailed, 'req.subprocess_env() is same size before and after'
-
- req.write("test ok")
return apache.OK
def req_add_handler(req):
@@ -75,24 +387,6 @@
req.write(req.document_root())
return apache.OK
-def req_get_config(req):
-
- if req.get_config() == apache.table({"PythonDebug":"1"}) and \
- req.get_options() == apache.table({"secret":"sauce"}):
- req.write("test ok")
-
- return apache.OK
-
-def req_get_remote_host(req):
-
- # simulating this test for real is too complex...
-
- if (req.get_remote_host(apache.REMOTE_HOST) == None) and \
- (req.get_remote_host() != ""):
- req.write("test ok")
-
- return apache.OK
-
def req_internal_redirect(req):
req.internal_redirect("/test.int")
@@ -158,7 +452,12 @@
def outputfilter(filter):
s = filter.read()
- filter.write(s.upper())
+ while s:
+ filter.write(s.upper())
+ s = filter.read()
+
+ if s is None:
+ filter.close()
return apache.OK
@@ -178,6 +477,8 @@
return apache.OK
def _test_table():
+
+ log = apache.log_error
d = apache.table()
if d.keys() != []: raise TestFailed, '{}.keys()'