Merge branch 'master' of github.com:mongodb/mongo-python-driver
This commit is contained in:
commit
a99ec0ed18
@ -227,17 +227,6 @@ functions:
|
||||
args:
|
||||
- ${DRIVERS_TOOLS}/.evergreen/atlas_data_lake/run-mongohouse-image.sh
|
||||
|
||||
"run mod_wsgi tests":
|
||||
- command: subprocess.exec
|
||||
type: test
|
||||
params:
|
||||
include_expansions_in_env: [MOD_WSGI_VERSION, MOD_WSGI_EMBEDDED, "PYTHON_BINARY"]
|
||||
working_dir: "src"
|
||||
binary: bash
|
||||
args:
|
||||
- .evergreen/scripts/run-with-env.sh
|
||||
- .evergreen/scripts/run-mod-wsgi-tests.sh
|
||||
|
||||
"run doctests":
|
||||
- command: subprocess.exec
|
||||
type: test
|
||||
@ -412,40 +401,6 @@ tasks:
|
||||
TEST_NAME: index_management
|
||||
AUTH: "auth"
|
||||
|
||||
- name: "mod-wsgi-standalone"
|
||||
tags: ["mod_wsgi"]
|
||||
commands:
|
||||
- func: "run server"
|
||||
vars:
|
||||
TOPOLOGY: "server"
|
||||
- func: "run mod_wsgi tests"
|
||||
|
||||
- name: "mod-wsgi-replica-set"
|
||||
tags: ["mod_wsgi"]
|
||||
commands:
|
||||
- func: "run server"
|
||||
vars:
|
||||
TOPOLOGY: "replica_set"
|
||||
- func: "run mod_wsgi tests"
|
||||
|
||||
- name: "mod-wsgi-embedded-mode-standalone"
|
||||
tags: ["mod_wsgi"]
|
||||
commands:
|
||||
- func: "run server"
|
||||
- func: "run mod_wsgi tests"
|
||||
vars:
|
||||
MOD_WSGI_EMBEDDED: "1"
|
||||
|
||||
- name: "mod-wsgi-embedded-mode-replica-set"
|
||||
tags: ["mod_wsgi"]
|
||||
commands:
|
||||
- func: "run server"
|
||||
vars:
|
||||
TOPOLOGY: "replica_set"
|
||||
- func: "run mod_wsgi tests"
|
||||
vars:
|
||||
MOD_WSGI_EMBEDDED: "1"
|
||||
|
||||
- name: "no-server"
|
||||
tags: ["no-server"]
|
||||
commands:
|
||||
|
||||
@ -775,6 +775,48 @@ tasks:
|
||||
TEST_NAME: load_balancer
|
||||
tags: [load-balancer, noauth, nossl]
|
||||
|
||||
# Mod wsgi tests
|
||||
- name: mod-wsgi-standalone
|
||||
commands:
|
||||
- func: run server
|
||||
vars:
|
||||
TOPOLOGY: standalone
|
||||
- func: run tests
|
||||
vars:
|
||||
TEST_NAME: mod_wsgi
|
||||
SUB_TEST_NAME: standalone
|
||||
tags: [mod_wsgi]
|
||||
- name: mod-wsgi-replica-set
|
||||
commands:
|
||||
- func: run server
|
||||
vars:
|
||||
TOPOLOGY: replica_set
|
||||
- func: run tests
|
||||
vars:
|
||||
TEST_NAME: mod_wsgi
|
||||
SUB_TEST_NAME: standalone
|
||||
tags: [mod_wsgi]
|
||||
- name: mod-wsgi-embedded-mode-standalone
|
||||
commands:
|
||||
- func: run server
|
||||
vars:
|
||||
TOPOLOGY: standalone
|
||||
- func: run tests
|
||||
vars:
|
||||
TEST_NAME: mod_wsgi
|
||||
SUB_TEST_NAME: embedded
|
||||
tags: [mod_wsgi]
|
||||
- name: mod-wsgi-embedded-mode-replica-set
|
||||
commands:
|
||||
- func: run server
|
||||
vars:
|
||||
TOPOLOGY: replica_set
|
||||
- func: run tests
|
||||
vars:
|
||||
TEST_NAME: mod_wsgi
|
||||
SUB_TEST_NAME: embedded
|
||||
tags: [mod_wsgi]
|
||||
|
||||
# Ocsp tests
|
||||
- name: test-ocsp-ecdsa-valid-cert-server-does-not-staple
|
||||
commands:
|
||||
|
||||
@ -696,10 +696,7 @@ buildvariants:
|
||||
# Mod wsgi tests
|
||||
- name: mod_wsgi-ubuntu-22-python3.9
|
||||
tasks:
|
||||
- name: mod-wsgi-standalone
|
||||
- name: mod-wsgi-replica-set
|
||||
- name: mod-wsgi-embedded-mode-standalone
|
||||
- name: mod-wsgi-embedded-mode-replica-set
|
||||
- name: .mod_wsgi
|
||||
display_name: mod_wsgi Ubuntu-22 Python3.9
|
||||
run_on:
|
||||
- ubuntu2204-small
|
||||
@ -708,10 +705,7 @@ buildvariants:
|
||||
PYTHON_BINARY: /opt/python/3.9/bin/python3
|
||||
- name: mod_wsgi-ubuntu-22-python3.13
|
||||
tasks:
|
||||
- name: mod-wsgi-standalone
|
||||
- name: mod-wsgi-replica-set
|
||||
- name: mod-wsgi-embedded-mode-standalone
|
||||
- name: mod-wsgi-embedded-mode-replica-set
|
||||
- name: .mod_wsgi
|
||||
display_name: mod_wsgi Ubuntu-22 Python3.13
|
||||
run_on:
|
||||
- ubuntu2204-small
|
||||
|
||||
@ -614,12 +614,7 @@ def create_atlas_data_lake_variants():
|
||||
def create_mod_wsgi_variants():
|
||||
variants = []
|
||||
host = HOSTS["ubuntu22"]
|
||||
tasks = [
|
||||
"mod-wsgi-standalone",
|
||||
"mod-wsgi-replica-set",
|
||||
"mod-wsgi-embedded-mode-standalone",
|
||||
"mod-wsgi-embedded-mode-replica-set",
|
||||
]
|
||||
tasks = [".mod_wsgi"]
|
||||
expansions = dict(MOD_WSGI_VERSION="4")
|
||||
for python in MIN_MAX_PYTHON:
|
||||
display_name = get_display_name("mod_wsgi", host, python=python)
|
||||
@ -892,6 +887,24 @@ def create_oidc_tasks():
|
||||
return tasks
|
||||
|
||||
|
||||
def create_mod_wsgi_tasks():
|
||||
tasks = []
|
||||
for test, topology in product(["standalone", "embedded-mode"], ["standalone", "replica_set"]):
|
||||
if test == "standalone":
|
||||
task_name = "mod-wsgi-"
|
||||
else:
|
||||
task_name = "mod-wsgi-embedded-mode-"
|
||||
task_name += topology.replace("_", "-")
|
||||
server_vars = dict(TOPOLOGY=topology)
|
||||
server_func = FunctionCall(func="run server", vars=server_vars)
|
||||
vars = dict(TEST_NAME="mod_wsgi", SUB_TEST_NAME=test.split("-")[0])
|
||||
test_func = FunctionCall(func="run tests", vars=vars)
|
||||
tags = ["mod_wsgi"]
|
||||
commands = [server_func, test_func]
|
||||
tasks.append(EvgTask(name=task_name, tags=tags, commands=commands))
|
||||
return tasks
|
||||
|
||||
|
||||
def _create_ocsp_task(algo, variant, server_type, base_task_name):
|
||||
file_name = f"{algo}-basic-tls-ocsp-{variant}.json"
|
||||
|
||||
|
||||
93
.evergreen/scripts/mod_wsgi_tester.py
Normal file
93
.evergreen/scripts/mod_wsgi_tester.py
Normal file
@ -0,0 +1,93 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import urllib.error
|
||||
import urllib.request
|
||||
from pathlib import Path
|
||||
from shutil import which
|
||||
|
||||
from utils import LOGGER, ROOT, run_command, write_env
|
||||
|
||||
|
||||
def make_request(url, timeout=10):
|
||||
for _ in range(int(timeout)):
|
||||
try:
|
||||
urllib.request.urlopen(url) # noqa: S310
|
||||
return
|
||||
except urllib.error.HTTPError:
|
||||
pass
|
||||
time.sleep(1)
|
||||
raise TimeoutError(f"Failed to access {url}")
|
||||
|
||||
|
||||
def setup_mod_wsgi(sub_test_name: str) -> None:
|
||||
env = os.environ.copy()
|
||||
if sub_test_name == "embedded":
|
||||
env["MOD_WSGI_CONF"] = "mod_wsgi_test_embedded.conf"
|
||||
elif sub_test_name == "standalone":
|
||||
env["MOD_WSGI_CONF"] = "mod_wsgi_test.conf"
|
||||
else:
|
||||
raise ValueError("mod_wsgi sub test must be either 'standalone' or 'embedded'")
|
||||
write_env("MOD_WSGI_CONF", env["MOD_WSGI_CONF"])
|
||||
apache = which("apache2")
|
||||
if not apache and Path("/usr/lib/apache2/mpm-prefork/apache2").exists():
|
||||
apache = "/usr/lib/apache2/mpm-prefork/apache2"
|
||||
if apache:
|
||||
apache_config = "apache24ubuntu161404.conf"
|
||||
else:
|
||||
apache = which("httpd")
|
||||
if not apache:
|
||||
raise ValueError("Could not find apache2 or httpd")
|
||||
apache_config = "apache22amazon.conf"
|
||||
python_version = ".".join(str(val) for val in sys.version_info[:2])
|
||||
mod_wsgi_version = 4
|
||||
so_file = f"/opt/python/mod_wsgi/python_version/{python_version}/mod_wsgi_version/{mod_wsgi_version}/mod_wsgi.so"
|
||||
write_env("MOD_WSGI_SO", so_file)
|
||||
env["MOD_WSGI_SO"] = so_file
|
||||
env["PYTHONHOME"] = f"/opt/python/{python_version}"
|
||||
env["PROJECT_DIRECTORY"] = project_directory = str(ROOT)
|
||||
write_env("APACHE_BINARY", apache)
|
||||
write_env("APACHE_CONFIG", apache_config)
|
||||
uri1 = f"http://localhost:8080/interpreter1{project_directory}"
|
||||
write_env("TEST_URI1", uri1)
|
||||
uri2 = f"http://localhost:8080/interpreter2{project_directory}"
|
||||
write_env("TEST_URI2", uri2)
|
||||
run_command(f"{apache} -k start -f {ROOT}/test/mod_wsgi_test/{apache_config}", env=env)
|
||||
|
||||
# Wait for the endpoints to be available.
|
||||
try:
|
||||
make_request(uri1, 10)
|
||||
make_request(uri2, 10)
|
||||
except Exception as e:
|
||||
LOGGER.error(Path("error_log").read_text())
|
||||
raise e
|
||||
|
||||
|
||||
def test_mod_wsgi() -> None:
|
||||
sys.path.insert(0, ROOT)
|
||||
from test.mod_wsgi_test.test_client import main, parse_args
|
||||
|
||||
uri1 = os.environ["TEST_URI1"]
|
||||
uri2 = os.environ["TEST_URI2"]
|
||||
args = f"-n 25000 -t 100 parallel {uri1} {uri2}"
|
||||
try:
|
||||
main(*parse_args(args.split()))
|
||||
|
||||
args = f"-n 25000 serial {uri1} {uri2}"
|
||||
main(*parse_args(args.split()))
|
||||
except Exception as e:
|
||||
LOGGER.error(Path("error_log").read_text())
|
||||
raise e
|
||||
|
||||
|
||||
def teardown_mod_wsgi() -> None:
|
||||
apache = os.environ["APACHE_BINARY"]
|
||||
apache_config = os.environ["APACHE_CONFIG"]
|
||||
|
||||
run_command(f"{apache} -k stop -f {ROOT}/test/mod_wsgi_test/{apache_config}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
setup_mod_wsgi()
|
||||
@ -1,53 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -o xtrace
|
||||
set -o errexit
|
||||
|
||||
APACHE=$(command -v apache2 || command -v /usr/lib/apache2/mpm-prefork/apache2) || true
|
||||
if [ -n "$APACHE" ]; then
|
||||
APACHE_CONFIG=apache24ubuntu161404.conf
|
||||
else
|
||||
APACHE=$(command -v httpd) || true
|
||||
if [ -z "$APACHE" ]; then
|
||||
echo "Could not find apache2 binary"
|
||||
exit 1
|
||||
else
|
||||
APACHE_CONFIG=apache22amazon.conf
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
PYTHON_VERSION=$(${PYTHON_BINARY} -c "import sys; sys.stdout.write('.'.join(str(val) for val in sys.version_info[:2]))")
|
||||
|
||||
# Ensure the C extensions are installed.
|
||||
${PYTHON_BINARY} -m venv --system-site-packages .venv
|
||||
source .venv/bin/activate
|
||||
pip install -U pip
|
||||
export PYMONGO_C_EXT_MUST_BUILD=1
|
||||
python -m pip install -v -e .
|
||||
|
||||
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
|
||||
# If MOD_WSGI_EMBEDDED is set use the default embedded mode behavior instead
|
||||
# of daemon mode (WSGIDaemonProcess).
|
||||
if [ -n "${MOD_WSGI_EMBEDDED:-}" ]; then
|
||||
export MOD_WSGI_CONF=mod_wsgi_test_embedded.conf
|
||||
else
|
||||
export MOD_WSGI_CONF=mod_wsgi_test.conf
|
||||
fi
|
||||
|
||||
cd ..
|
||||
$APACHE -k start -f ${PROJECT_DIRECTORY}/test/mod_wsgi_test/${APACHE_CONFIG}
|
||||
trap '$APACHE -k stop -f ${PROJECT_DIRECTORY}/test/mod_wsgi_test/${APACHE_CONFIG}' EXIT HUP
|
||||
|
||||
wget -t 1 -T 10 -O - "http://localhost:8080/interpreter1${PROJECT_DIRECTORY}" || (cat error_log && exit 1)
|
||||
wget -t 1 -T 10 -O - "http://localhost:8080/interpreter2${PROJECT_DIRECTORY}" || (cat error_log && exit 1)
|
||||
|
||||
python ${PROJECT_DIRECTORY}/test/mod_wsgi_test/test_client.py -n 25000 -t 100 parallel \
|
||||
http://localhost:8080/interpreter1${PROJECT_DIRECTORY} http://localhost:8080/interpreter2${PROJECT_DIRECTORY} || \
|
||||
(tail -n 100 error_log && exit 1)
|
||||
|
||||
python ${PROJECT_DIRECTORY}/test/mod_wsgi_test/test_client.py -n 25000 serial \
|
||||
http://localhost:8080/interpreter1${PROJECT_DIRECTORY} http://localhost:8080/interpreter2${PROJECT_DIRECTORY} || \
|
||||
(tail -n 100 error_log && exit 1)
|
||||
|
||||
rm -rf .venv
|
||||
@ -100,6 +100,13 @@ def run() -> None:
|
||||
if TEST_PERF:
|
||||
start_time = datetime.now()
|
||||
|
||||
# Run mod_wsgi tests using the helper.
|
||||
if TEST_NAME == "mod_wsgi":
|
||||
from mod_wsgi_tester import test_mod_wsgi
|
||||
|
||||
test_mod_wsgi()
|
||||
return
|
||||
|
||||
# Send kms tests to run remotely.
|
||||
if TEST_NAME == "kms" and SUB_TEST_NAME in ["azure", "gcp"]:
|
||||
from kms_tester import test_kms_send_to_remote
|
||||
|
||||
@ -251,6 +251,11 @@ def handle_test_env() -> None:
|
||||
cmd = f'bash "{DRIVERS_TOOLS}/.evergreen/run-load-balancer.sh" start'
|
||||
run_command(cmd)
|
||||
|
||||
if test_name == "mod_wsgi":
|
||||
from mod_wsgi_tester import setup_mod_wsgi
|
||||
|
||||
setup_mod_wsgi(sub_test_name)
|
||||
|
||||
if test_name == "ocsp":
|
||||
if sub_test_name:
|
||||
os.environ["OCSP_SERVER_TYPE"] = sub_test_name
|
||||
@ -381,7 +386,7 @@ def handle_test_env() -> None:
|
||||
# Use --capture=tee-sys so pytest prints test output inline:
|
||||
# https://docs.pytest.org/en/stable/how-to/capture-stdout-stderr.html
|
||||
TEST_ARGS = f"-v --capture=tee-sys --durations=5 {TEST_ARGS}"
|
||||
TEST_SUITE = TEST_SUITE_MAP[test_name]
|
||||
TEST_SUITE = TEST_SUITE_MAP.get(test_name)
|
||||
if TEST_SUITE:
|
||||
TEST_ARGS = f"-m {TEST_SUITE} {TEST_ARGS}"
|
||||
|
||||
|
||||
@ -44,4 +44,10 @@ elif TEST_NAME == "serverless":
|
||||
elif TEST_NAME == "auth_aws" and sys.platform != "darwin":
|
||||
run_command(f"bash {DRIVERS_TOOLS}/.evergreen/auth_aws/teardown.sh")
|
||||
|
||||
# Tear down mog_wsgi if applicable.
|
||||
elif TEST_NAME == "mod_wsgi":
|
||||
from mod_wsgi_tester import teardown_mod_wsgi
|
||||
|
||||
teardown_mod_wsgi()
|
||||
|
||||
LOGGER.info(f"Tearing down tests of type '{TEST_NAME}'... done.")
|
||||
|
||||
@ -50,7 +50,9 @@ TEST_SUITE_MAP = {
|
||||
}
|
||||
|
||||
# Tests that require a sub test suite.
|
||||
SUB_TEST_REQUIRED = ["auth_aws", "auth_oidc", "kms"]
|
||||
SUB_TEST_REQUIRED = ["auth_aws", "auth_oidc", "kms", "mod_wsgi"]
|
||||
|
||||
EXTRA_TESTS = ["mod_wsgi"]
|
||||
|
||||
|
||||
def get_test_options(
|
||||
@ -62,7 +64,7 @@ def get_test_options(
|
||||
if require_sub_test_name:
|
||||
parser.add_argument(
|
||||
"test_name",
|
||||
choices=sorted(TEST_SUITE_MAP),
|
||||
choices=sorted(list(TEST_SUITE_MAP) + EXTRA_TESTS),
|
||||
nargs="?",
|
||||
default="default",
|
||||
help="The optional name of the test suite to set up, typically the same name as a pytest marker.",
|
||||
@ -137,6 +139,11 @@ def run_command(cmd: str | list[str], **kwargs: Any) -> None:
|
||||
cmd = " ".join(cmd)
|
||||
LOGGER.info("Running command '%s'...", cmd)
|
||||
kwargs.setdefault("check", True)
|
||||
# Prevent overriding the python used by other tools.
|
||||
env = kwargs.pop("env", os.environ).copy()
|
||||
if "UV_PYTHON" in env:
|
||||
del env["UV_PYTHON"]
|
||||
kwargs["env"] = env
|
||||
try:
|
||||
subprocess.run(shlex.split(cmd), **kwargs) # noqa: PLW1510, S603
|
||||
except subprocess.CalledProcessError as e:
|
||||
|
||||
@ -275,6 +275,17 @@ Note: these tests can only be run from an Evergreen host.
|
||||
- Run `just setup-tests atlas_connect`.
|
||||
- Run `just run-tests`.
|
||||
|
||||
### mod_wsgi tests
|
||||
|
||||
Note: these tests can only be run from an Evergreen Linux host that has the Python toolchain.
|
||||
|
||||
- Run `just run-server`.
|
||||
- Run `just setup-tests mod_wsgi <mode>`.
|
||||
- Run `just run-tests`.
|
||||
|
||||
The `mode` can be `standalone` or `embedded`. For the `replica_set` version of the tests, use
|
||||
`TOPOLOGY=replica_set just run-server`.
|
||||
|
||||
### OCSP tests
|
||||
|
||||
- Export the orchestration file, e.g. `export ORCHESTRATION_FILE=rsa-basic-tls-ocsp-disableStapling.json`.
|
||||
|
||||
@ -24,7 +24,7 @@ from optparse import OptionParser
|
||||
from urllib.request import urlopen
|
||||
|
||||
|
||||
def parse_args():
|
||||
def parse_args(args=None):
|
||||
parser = OptionParser(
|
||||
"""usage: %prog [options] mode url [<url2>...]
|
||||
|
||||
@ -70,7 +70,7 @@ def parse_args():
|
||||
)
|
||||
|
||||
try:
|
||||
options, args = parser.parse_args()
|
||||
options, args = parser.parse_args(args or sys.argv[1:])
|
||||
mode, urls = args[0], args[1:]
|
||||
except (ValueError, IndexError):
|
||||
parser.print_usage()
|
||||
@ -103,11 +103,11 @@ class URLGetterThread(threading.Thread):
|
||||
def run(self):
|
||||
for _i in range(self.nrequests_per_thread):
|
||||
try:
|
||||
get(urls)
|
||||
get(self.urls)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
if not options.continue_:
|
||||
if not self.options.continue_:
|
||||
thread.interrupt_main()
|
||||
thread.exit()
|
||||
|
||||
@ -117,7 +117,7 @@ class URLGetterThread(threading.Thread):
|
||||
URLGetterThread.counter += 1
|
||||
counter = URLGetterThread.counter
|
||||
|
||||
should_print = options.verbose and not counter % 1000
|
||||
should_print = self.options.verbose and not counter % 1000
|
||||
|
||||
if should_print:
|
||||
print(counter)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user