diff --git a/.evergreen/config.yml b/.evergreen/config.yml index 4dfaedaae..e423aeee9 100644 --- a/.evergreen/config.yml +++ b/.evergreen/config.yml @@ -327,6 +327,15 @@ functions: ${PREPARE_SHELL} sh ${DRIVERS_TOOLS}/.evergreen/stop-orchestration.sh + "run mod_wsgi tests": + - command: shell.exec + type: test + params: + working_dir: "src" + script: | + ${PREPARE_SHELL} + PYTHON_BINARY=${PYTHON_BINARY} MOD_WSGI_VERSION=${MOD_WSGI_VERSION} PROJECT_DIRECTORY=${PROJECT_DIRECTORY} sh ${PROJECT_DIRECTORY}/.evergreen/run-mod-wsgi-tests.sh + "run tests": - command: shell.exec type: test @@ -622,6 +631,24 @@ tasks: TOPOLOGY: "server" - func: "run enterprise auth tests" + - name: "mod-wsgi-standalone" + tags: ["mod_wsgi"] + commands: + - func: "bootstrap mongo-orchestration" + vars: + VERSION: "latest" + TOPOLOGY: "server" + - func: "run mod_wsgi tests" + + - name: "mod-wsgi-replica-set" + tags: ["mod_wsgi"] + commands: + - func: "bootstrap mongo-orchestration" + vars: + VERSION: "latest" + TOPOLOGY: "replica_set" + - func: "run mod_wsgi tests" + # }}} @@ -842,6 +869,21 @@ axes: display_name: "Jython 2.7" variables: PYTHON_BINARY: "/opt/python/jython2.7/bin/jython" + - id: mod-wsgi-version + display_name: "mod_wsgi version" + values: + - id: "2.8" + display_name: "mod_wsgi 2.8" + variables: + MOD_WSGI_VERSION: "2.8" + - id: "3.5" + display_name: "mod_wsgi 3.5" + variables: + MOD_WSGI_VERSION: "3.5" + - id: "4.5.15" + display_name: "mod_wsgi 4.5.15" + variables: + MOD_WSGI_VERSION: "4.5.15" - id: c-extensions display_name: "C Extensions" values: @@ -1068,6 +1110,16 @@ buildvariants: tasks: - name: "test-enterprise-auth" +- matrix_name: "tests-mod-wsgi" + matrix_spec: {"python-version": ["2.4", "2.6", "2.7"], "mod-wsgi-version": "*"} + exclude_spec: + python-version: ["2.4"] + mod-wsgi-version: ["3.5", "4.5.15"] + display_name: "${mod-wsgi-version} ${python-version}" + run_on: ubuntu1204-test + tasks: + - ".mod_wsgi" + # Platform notes # i386 builds of OpenSSL or Cyrus SASL are not available # Ubuntu14.04 only supports 2.6+ with SSL diff --git a/.evergreen/run-mod-wsgi-tests.sh b/.evergreen/run-mod-wsgi-tests.sh new file mode 100644 index 000000000..d20961085 --- /dev/null +++ b/.evergreen/run-mod-wsgi-tests.sh @@ -0,0 +1,47 @@ +#!/bin/sh +set -o xtrace +set -o errexit + +APACHE=$(command -v apache2 || command -v /usr/lib/apache2/mpm-prefork/apache2) || true +if [ -z "$APACHE" ]; then + echo "Could not find apache2 binary" + exit 1 +fi + +PYTHON_VERSION=$(${PYTHON_BINARY} -c "import sys; sys.stdout.write('.'.join(str(val) for val in sys.version_info[:2]))") + +if [ $MOD_WSGI_VERSION = "2.8" ] && [ $PYTHON_VERSION = "2.7" ]; then + # mod_wsgi 2.8 segfaults when built against the toolchain Python 2.7. Build + # against the system Python 2.7 instead. + git clone https://github.com/GrahamDumpleton/mod_wsgi.git + cd mod_wsgi + git checkout tags/2.8 + ./configure + make + export MOD_WSGI_SO=$(pwd)/.libs/mod_wsgi.so + cd .. +else + export MOD_WSGI_SO=/opt/python/mod_wsgi/python_version/$PYTHON_VERSION/mod_wsgi_version/$MOD_WSGI_VERSION/mod_wsgi.so + export PYTHONHOME=/opt/python/$PYTHON_VERSION +fi + +cd .. +$APACHE -k start -f ${PROJECT_DIRECTORY}/test/mod_wsgi_test/apache22ubuntu1204.conf +trap "$APACHE -k stop -f ${PROJECT_DIRECTORY}/test/mod_wsgi_test/apache22ubuntu1204.conf" EXIT HUP + +set +e +wget -t 1 -T 10 -O - "http://localhost:8080${PROJECT_DIRECTORY}" +STATUS=$? +set -e + +# Debug +cat error_log + +if [ $STATUS != 0 ]; then + exit $STATUS +fi + +${PYTHON_BINARY} ${PROJECT_DIRECTORY}/test/mod_wsgi_test/test_client.py -n 25000 -t 100 parallel http://localhost:8080${PROJECT_DIRECTORY} + +${PYTHON_BINARY} ${PROJECT_DIRECTORY}/test/mod_wsgi_test/test_client.py -n 25000 serial http://localhost:8080${PROJECT_DIRECTORY} + diff --git a/test/mod_wsgi_test/README.rst b/test/mod_wsgi_test/README.rst index 128413a13..5ca4e933e 100644 --- a/test/mod_wsgi_test/README.rst +++ b/test/mod_wsgi_test/README.rst @@ -27,17 +27,12 @@ Compile Python We need a Python interpreter built as a shared library. Download the source tarball for each Python version tested, untar it, and run:: - ./configure --prefix=/some/directory --enable-shared + ./configure --prefix=/some/directory --enable-shared LDFLAGS="-Wl,--rpath=/some/directory/lib" make make install -This results in an executable named "python" and a shared -library named something like "libpython2.7.so.1.0". -It may be necessary to add /some/directory/lib to your system's -LD_LIBRARY_PATH, or to make a symlink from your system's default library -directory to the shared library. For example, on Ubuntu:: - - ln -s /some/directory/lib/libpython2.7.so.1.0 /usr/lib64/ +This results in an executable named "python" or "python3" and a shared +library named something like "libpython2.7.so.1.0" or "libpython3.3m.so.1.0". Compile mod_wsgi ................ @@ -50,7 +45,7 @@ RedHat-like Linux:: wget https://modwsgi.googlecode.com/files/mod_wsgi-3.4.tar.gz tar xzf mod_wsgi-3.4.tar.gz cd mod_wsgi-3.4 - ./configure --with-python=/some/directory/python + ./configure --with-python=/some/directory/bin/python LDFLAGS="-Wl,--rpath=/some/directory/lib" make make install @@ -66,8 +61,12 @@ listening on port 27017. Configure Apache ................ -Copy the appropriate version of ``mod_wsgi.so`` into Apache's modules -directory. Start Apache with the ``mod_wsgi_test.conf`` in this directory. +Set a MOD_WSGI_SO environment variable so our ``mod_wsgi_test.conf`` +can find and load mod_wsgi.so:: + + export MOD_WSGI_SO=/path/to/mod_wsgi.so + +Start Apache with one of the config files in this directory. Run the test ------------ @@ -90,7 +89,7 @@ The ``test_client.py`` script merely makes HTTP requests to Apache. Its exit code is non-zero if any of its requests fails, for example with an HTTP 500. -The core of the test is in the WSGI script, ``mod_wsgi_test.wsgi`. +The core of the test is in the WSGI script, ``mod_wsgi_test.wsgi``. This script inserts some documents into MongoDB at startup, then queries documents for each HTTP request. @@ -100,7 +99,6 @@ the test will fail when PyMongo exhausts its file descriptors. Automation ---------- -At MongoDB, Inc. we use a Jenkins job that tests each combination in the -matrix. The job copies the appropriate version of ``mod_wsgi.so`` into -place, sets up Apache, starts a single server or replica set, -and runs ``test_client.py`` with the proper arguments. +At MongoDB, Inc. we use a continuous integration job that tests each +combination in the matrix. The job starts up Apache, starts a single server +or replica set, and runs ``test_client.py`` with the proper arguments. diff --git a/test/mod_wsgi_test/apache22amazon.conf b/test/mod_wsgi_test/apache22amazon.conf new file mode 100644 index 000000000..97ab0d997 --- /dev/null +++ b/test/mod_wsgi_test/apache22amazon.conf @@ -0,0 +1,31 @@ +# This is a minimal httpd.conf file written for Apache 2.2 on Amazon Linux + +# The modules directory is here by default. +# ServerRoot "/etc/httpd" +DocumentRoot ${PWD} +PidFile ${PWD}/apache2.pid + +# Bind to localhost only, don't require sudo. +Listen 127.0.0.1:8080 + +# Required modules. +LoadModule authz_host_module modules/mod_authz_host.so +# Needed so we can set a custom log location. +LoadModule log_config_module modules/mod_log_config.so + +ErrorLog ${PWD}/error_log +CustomLog ${PWD}/access_log combined + + + AllowOverride None + Order Deny,Allow + Deny from All + + + + AllowOverride None + Order Allow,Deny + Allow from All + + +Include ${PROJECT_DIRECTORY}/test/mod_wsgi_test/mod_wsgi_test.conf diff --git a/test/mod_wsgi_test/apache22ubuntu1204.conf b/test/mod_wsgi_test/apache22ubuntu1204.conf new file mode 100644 index 000000000..9ff257bc3 --- /dev/null +++ b/test/mod_wsgi_test/apache22ubuntu1204.conf @@ -0,0 +1,29 @@ +# This is a minimal httpd.conf file written for Apache 2.2 on Ubuntu 12.04 + +# The modules directory is here on Ubuntu. +ServerRoot "/usr/lib/apache2" +DocumentRoot ${PWD} +PidFile ${PWD}/apache2.pid + +# Bind to localhost only, don't require sudo. +Listen 127.0.0.1:8080 + +# Required modules. +LoadModule authz_host_module modules/mod_authz_host.so + +ErrorLog ${PWD}/error_log +CustomLog ${PWD}/access_log combined + + + AllowOverride None + Order Deny,Allow + Deny from All + + + + AllowOverride None + Order Allow,Deny + Allow from All + + +Include ${PROJECT_DIRECTORY}/test/mod_wsgi_test/mod_wsgi_test.conf diff --git a/test/mod_wsgi_test/mod_wsgi_test.conf b/test/mod_wsgi_test/mod_wsgi_test.conf index 987d93e8e..9505933e9 100644 --- a/test/mod_wsgi_test/mod_wsgi_test.conf +++ b/test/mod_wsgi_test/mod_wsgi_test.conf @@ -14,7 +14,7 @@ # Minimal test of PyMongo in a WSGI application, see bug PYTHON-353 -LoadModule wsgi_module modules/mod_wsgi.so +LoadModule wsgi_module ${MOD_WSGI_SO} # Avoid permissions issues WSGISocketPrefix /tmp/ diff --git a/test/mod_wsgi_test/mod_wsgi_test.wsgi b/test/mod_wsgi_test/mod_wsgi_test.wsgi index 2dffd9973..1c02722df 100644 --- a/test/mod_wsgi_test/mod_wsgi_test.wsgi +++ b/test/mod_wsgi_test/mod_wsgi_test.wsgi @@ -55,7 +55,7 @@ except: def application(environ, start_response): results = list(collection.find().batch_size(10)) assert len(results) == ndocs - output = 'python %s, mod_wsgi %s, pymongo %s' % ( + output = ' python %s, mod_wsgi %s, pymongo %s ' % ( sys.version, mod_wsgi_version, pymongo.version) response_headers = [('Content-Length', str(len(output)))] start_response('200 OK', response_headers)