PYTHON-4565 - Use pytest markers for test suite configuration (#1741)

This commit is contained in:
Noah Stapp 2024-07-23 12:28:55 -07:00 committed by GitHub
parent 272538513a
commit 993171cd3d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
38 changed files with 682 additions and 382 deletions

View File

@ -30,7 +30,7 @@ set -o xtrace
AUTH=${AUTH:-noauth}
SSL=${SSL:-nossl}
TEST_SUITES="test/ test/asynchronous/"
TEST_SUITES=""
TEST_ARGS="${*:1}"
export PIP_QUIET=1 # Quiet by default
@ -96,7 +96,7 @@ if [ -n "$TEST_LOADBALANCER" ]; then
export LOAD_BALANCER=1
export SINGLE_MONGOS_LB_URI="${SINGLE_MONGOS_LB_URI:-mongodb://127.0.0.1:8000/?loadBalanced=true}"
export MULTI_MONGOS_LB_URI="${MULTI_MONGOS_LB_URI:-mongodb://127.0.0.1:8001/?loadBalanced=true}"
export TEST_SUITES="test/test_load_balancer.py"
export TEST_SUITES="load_balancer"
fi
if [ "$SSL" != "nossl" ]; then
@ -172,7 +172,7 @@ if [ -n "$TEST_ENCRYPTION" ]; then
export PATH=$CRYPT_SHARED_DIR:$PATH
fi
# Only run the encryption tests.
TEST_SUITES="test/test_encryption.py"
TEST_SUITES="encryption"
fi
if [ -n "$TEST_FLE_AZURE_AUTO" ] || [ -n "$TEST_FLE_GCP_AUTO" ]; then
@ -185,8 +185,7 @@ if [ -n "$TEST_FLE_AZURE_AUTO" ] || [ -n "$TEST_FLE_GCP_AUTO" ]; then
echo "MONGODB_URI unexpectedly contains user credentials in FLE test!";
exit 1
fi
TEST_SUITES="test/test_on_demand_csfle.py"
TEST_SUITES="csfle"
fi
if [ -n "$TEST_INDEX_MANAGEMENT" ]; then
@ -195,36 +194,36 @@ if [ -n "$TEST_INDEX_MANAGEMENT" ]; then
set +x
export DB_PASSWORD="${DRIVERS_ATLAS_LAMBDA_PASSWORD}"
set -x
TEST_SUITES="test/test_index_management.py"
TEST_SUITES="index_management"
fi
if [ -n "$TEST_DATA_LAKE" ] && [ -z "$TEST_ARGS" ]; then
TEST_SUITES="test/test_data_lake.py"
TEST_SUITES="data_lake"
fi
if [ -n "$TEST_ATLAS" ]; then
TEST_SUITES="test/atlas/test_connection.py"
TEST_SUITES="atlas"
fi
if [ -n "$TEST_OCSP" ]; then
python -m pip install ".[ocsp]"
TEST_SUITES="test/ocsp/test_ocsp.py"
TEST_SUITES="ocsp"
fi
if [ -n "$TEST_AUTH_AWS" ]; then
python -m pip install ".[aws]"
TEST_SUITES="test/auth_aws/test_auth_aws.py"
TEST_SUITES="auth_aws"
fi
if [ -n "$TEST_AUTH_OIDC" ]; then
python -m pip install ".[aws]"
TEST_SUITES="test/auth_oidc/test_auth_oidc.py $TEST_ARGS"
TEST_SUITES="auth_oidc"
fi
if [ -n "$PERF_TEST" ]; then
python -m pip install simplejson
start_time=$(date +%s)
TEST_SUITES="test/performance/perf_test.py"
TEST_SUITES="perf"
fi
echo "Running $AUTH tests over $SSL with python $(which python)"
@ -254,7 +253,11 @@ PIP_QUIET=0 python -m pip list
if [ -z "$GREEN_FRAMEWORK" ]; then
# Use --capture=tee-sys so pytest prints test output inline:
# https://docs.pytest.org/en/stable/how-to/capture-stdout-stderr.html
python -m pytest -v --capture=tee-sys --durations=5 --maxfail=10 $TEST_SUITES $TEST_ARGS
if [ -z "$TEST_SUITES" ]; then
python -m pytest -v --capture=tee-sys --durations=5 --maxfail=10 $TEST_ARGS
else
python -m pytest -v --capture=tee-sys --durations=5 --maxfail=10 -m $TEST_SUITES $TEST_ARGS
fi
else
python green_framework_test.py $GREEN_FRAMEWORK -v $TEST_ARGS
fi

View File

@ -42,7 +42,7 @@ features = ["test"]
test = "pytest -v --durations=5 --maxfail=10 {args}"
test-eg = "bash ./.evergreen/run-tests.sh {args}"
test-async = "test test/asynchronous/ {args}"
test-mockupdb = ["pip install -U git+https://github.com/ajdavis/mongo-mockup-db@master", "test ./test/mockupdb"]
test-mockupdb = ["pip install -U git+https://github.com/ajdavis/mongo-mockup-db@master", "test -m mockupdb"]
[envs.encryption]
skip-install = true

View File

@ -70,10 +70,9 @@ zstd = ["requirements/zstd.txt"]
[tool.pytest.ini_options]
minversion = "7"
addopts = ["-ra", "--strict-config", "--strict-markers", "--junitxml=xunit-results/TEST-results.xml"]
addopts = ["-ra", "--strict-config", "--strict-markers", "--junitxml=xunit-results/TEST-results.xml", "-m default"]
testpaths = ["test"]
log_cli_level = "INFO"
norecursedirs = ["test/*"]
faulthandler_timeout = 1500
xfail_strict = true
filterwarnings = [
@ -96,6 +95,20 @@ filterwarnings = [
# https://github.com/dateutil/dateutil/issues/1314
"module:datetime.datetime.utc:DeprecationWarning:dateutil",
]
markers = [
"auth_aws: tests that rely on pymongo-auth-aws",
"auth_oidc: tests that rely on oidc auth",
"ocsp: tests that rely on ocsp",
"atlas: tests that rely on atlas",
"data_lake: tests that rely on atlas data lake",
"perf: benchmark tests",
"index_management: index management tests",
"csfle: client-side field-level encryption tests",
"encryption: encryption tests",
"load_balancer: load balancer tests",
"mockupdb: tests that rely on mockupdb",
"default: default test suite",
]
[tool.mypy]
strict = true

View File

@ -12,3 +12,9 @@ async def test_setup_and_teardown():
await async_setup()
yield
await async_teardown()
def pytest_collection_modifyitems(items, config):
for item in items:
if not any(item.iter_markers()):
item.add_marker("default")

View File

@ -20,11 +20,16 @@ import sys
import unittest
from collections import defaultdict
import pytest
sys.path[0:0] = [""]
import pymongo
from pymongo.ssl_support import HAS_SNI
pytestmark = pytest.mark.atlas
URIS = {
"ATLAS_REPL": os.environ.get("ATLAS_REPL"),
"ATLAS_SHRD": os.environ.get("ATLAS_SHRD"),

View File

@ -20,14 +20,21 @@ import sys
import unittest
from unittest.mock import patch
import pytest
sys.path[0:0] = [""]
from pymongo_auth_aws import AwsCredential, auth
try:
from pymongo_auth_aws import AwsCredential, auth
except ImportError:
pass
from pymongo import MongoClient
from pymongo.errors import OperationFailure
from pymongo.uri_parser import parse_uri
pytestmark = pytest.mark.auth_aws
class TestAuthAWS(unittest.TestCase):
uri: str

View File

@ -25,6 +25,8 @@ from contextlib import contextmanager
from pathlib import Path
from typing import Dict
import pytest
sys.path[0:0] = [""]
from test.unified_format import generate_test_classes
@ -55,6 +57,8 @@ TOKEN_FILE = os.environ.get("OIDC_TOKEN_FILE", "")
# Generate unified tests.
globals().update(generate_test_classes(str(TEST_PATH), module=__name__))
pytestmark = pytest.mark.auth_oidc
class OIDCTestBase(unittest.TestCase):
@classmethod
@ -96,6 +100,7 @@ class OIDCTestBase(unittest.TestCase):
client.admin.command("configureFailPoint", cmd_on["configureFailPoint"], mode="off")
@pytest.mark.auth_oidc
class TestAuthOIDCHuman(OIDCTestBase):
uri: str

View File

@ -12,3 +12,9 @@ def test_setup_and_teardown():
setup()
yield
teardown()
def pytest_collection_modifyitems(items, config):
for item in items:
if not any(item.iter_markers()):
item.add_marker("default")

View File

@ -15,7 +15,12 @@ from __future__ import annotations
from collections import namedtuple
from mockupdb import OpMsgReply, OpReply
try:
from mockupdb import OpMsgReply, OpReply
_HAVE_MOCKUPDB = True
except ImportError:
_HAVE_MOCKUPDB = False
from pymongo import ReadPreference
@ -51,67 +56,69 @@ secondaries in a replica set, or select a mongos for secondary reads in a
sharded cluster (PYTHON-868).
"""
not_master_reply = OpMsgReply(ok=0, errmsg="not master")
operations = [
Operation(
"find_one",
lambda client: client.db.collection.find_one(),
reply={"cursor": {"id": 0, "firstBatch": []}},
op_type="may-use-secondary",
not_master=not_master_reply,
),
Operation(
"count_documents",
lambda client: client.db.collection.count_documents({}),
reply={"n": 1},
op_type="may-use-secondary",
not_master=not_master_reply,
),
Operation(
"estimated_document_count",
lambda client: client.db.collection.estimated_document_count(),
reply={"n": 1},
op_type="may-use-secondary",
not_master=not_master_reply,
),
Operation(
"aggregate",
lambda client: client.db.collection.aggregate([]),
reply={"cursor": {"id": 0, "firstBatch": []}},
op_type="may-use-secondary",
not_master=not_master_reply,
),
Operation(
"options",
lambda client: client.db.collection.options(),
reply={"cursor": {"id": 0, "firstBatch": []}},
op_type="must-use-primary",
not_master=not_master_reply,
),
Operation(
"command",
lambda client: client.db.command("foo"),
reply={"ok": 1},
op_type="must-use-primary", # Ignores client's read preference.
not_master=not_master_reply,
),
Operation(
"secondary command",
lambda client: client.db.command("foo", read_preference=ReadPreference.SECONDARY),
reply={"ok": 1},
op_type="always-use-secondary",
not_master=OpReply(ok=0, errmsg="node is recovering"),
),
Operation(
"listIndexes",
lambda client: client.db.collection.index_information(),
reply={"cursor": {"id": 0, "firstBatch": []}},
op_type="must-use-primary",
not_master=not_master_reply,
),
]
if _HAVE_MOCKUPDB:
not_master_reply = OpMsgReply(ok=0, errmsg="not master")
operations = [
Operation(
"find_one",
lambda client: client.db.collection.find_one(),
reply={"cursor": {"id": 0, "firstBatch": []}},
op_type="may-use-secondary",
not_master=not_master_reply,
),
Operation(
"count_documents",
lambda client: client.db.collection.count_documents({}),
reply={"n": 1},
op_type="may-use-secondary",
not_master=not_master_reply,
),
Operation(
"estimated_document_count",
lambda client: client.db.collection.estimated_document_count(),
reply={"n": 1},
op_type="may-use-secondary",
not_master=not_master_reply,
),
Operation(
"aggregate",
lambda client: client.db.collection.aggregate([]),
reply={"cursor": {"id": 0, "firstBatch": []}},
op_type="may-use-secondary",
not_master=not_master_reply,
),
Operation(
"options",
lambda client: client.db.collection.options(),
reply={"cursor": {"id": 0, "firstBatch": []}},
op_type="must-use-primary",
not_master=not_master_reply,
),
Operation(
"command",
lambda client: client.db.command("foo"),
reply={"ok": 1},
op_type="must-use-primary", # Ignores client's read preference.
not_master=not_master_reply,
),
Operation(
"secondary command",
lambda client: client.db.command("foo", read_preference=ReadPreference.SECONDARY),
reply={"ok": 1},
op_type="always-use-secondary",
not_master=OpReply(ok=0, errmsg="node is recovering"),
),
Operation(
"listIndexes",
lambda client: client.db.collection.index_information(),
reply={"cursor": {"id": 0, "firstBatch": []}},
op_type="must-use-primary",
not_master=not_master_reply,
),
]
else:
operations = []
_ops_by_name = {op.name: op for op in operations}

View File

@ -15,11 +15,20 @@ from __future__ import annotations
import unittest
from mockupdb import MockupDB
import pytest
try:
from mockupdb import MockupDB
_HAVE_MOCKUPDB = True
except ImportError:
_HAVE_MOCKUPDB = False
from pymongo import MongoClient
from pymongo.errors import ServerSelectionTimeoutError
pytestmark = pytest.mark.mockupdb
class TestAuthRecoveringMember(unittest.TestCase):
def test_auth_recovering_member(self):

View File

@ -17,11 +17,21 @@ from __future__ import annotations
import unittest
from mockupdb import MockupDB, going
import pytest
try:
from mockupdb import MockupDB, going
_HAVE_MOCKUPDB = True
except ImportError:
_HAVE_MOCKUPDB = False
from bson import Timestamp
from pymongo import DeleteMany, InsertOne, MongoClient, UpdateOne
pytestmark = pytest.mark.mockupdb
class TestClusterTime(unittest.TestCase):
def cluster_time_conversation(self, callback, replies):

View File

@ -18,12 +18,22 @@ from __future__ import annotations
import unittest
from test import PyMongoTestCase
from mockupdb import MockupDB, OpMsg, going
import pytest
try:
from mockupdb import MockupDB, OpMsg, going
_HAVE_MOCKUPDB = True
except ImportError:
_HAVE_MOCKUPDB = False
from bson.objectid import ObjectId
from pymongo import MongoClient
from pymongo.errors import OperationFailure
pytestmark = pytest.mark.mockupdb
class TestCursor(unittest.TestCase):
def test_getmore_load_balanced(self):

View File

@ -17,10 +17,20 @@ from __future__ import annotations
import unittest
from mockupdb import MockupDB, going
import pytest
try:
from mockupdb import MockupDB, going
_HAVE_MOCKUPDB = True
except ImportError:
_HAVE_MOCKUPDB = False
from pymongo import MongoClient
pytestmark = pytest.mark.mockupdb
class TestCursorNamespace(unittest.TestCase):
server: MockupDB

View File

@ -18,10 +18,20 @@ from __future__ import annotations
import unittest
from queue import Queue
from mockupdb import MockupDB, going
import pytest
try:
from mockupdb import MockupDB, going
_HAVE_MOCKUPDB = True
except ImportError:
_HAVE_MOCKUPDB = False
from pymongo import MongoClient
pytestmark = pytest.mark.mockupdb
class TestGetmoreSharded(unittest.TestCase):
def test_getmore_sharded(self):

View File

@ -15,7 +15,15 @@ from __future__ import annotations
import unittest
from mockupdb import Command, MockupDB, OpMsg, OpMsgReply, OpQuery, OpReply, absent, go
import pytest
try:
from mockupdb import Command, MockupDB, OpMsg, OpMsgReply, OpQuery, OpReply, absent, go
_HAVE_MOCKUPDB = True
except ImportError:
_HAVE_MOCKUPDB = False
from bson.objectid import ObjectId
from pymongo import MongoClient
@ -23,6 +31,8 @@ from pymongo import version as pymongo_version
from pymongo.errors import OperationFailure
from pymongo.server_api import ServerApi, ServerApiVersion
pytestmark = pytest.mark.mockupdb
def _check_handshake_data(request):
assert "client" in request

View File

@ -16,10 +16,20 @@ from __future__ import annotations
import time
import unittest
from mockupdb import MockupDB, wait_until
import pytest
try:
from mockupdb import MockupDB, wait_until
_HAVE_MOCKUPDB = True
except ImportError:
_HAVE_MOCKUPDB = False
from pymongo import MongoClient
pytestmark = pytest.mark.mockupdb
class TestInitialIsMaster(unittest.TestCase):
def test_initial_ismaster(self):

View File

@ -17,11 +17,21 @@ from __future__ import annotations
import unittest
from mockupdb import MockupDB, going
import pytest
try:
from mockupdb import MockupDB, going
_HAVE_MOCKUPDB = True
except ImportError:
_HAVE_MOCKUPDB = False
from bson import SON
from pymongo import MongoClient
pytestmark = pytest.mark.mockupdb
class TestListIndexes(unittest.TestCase):
def test_list_indexes_command(self):

View File

@ -15,10 +15,20 @@ from __future__ import annotations
import unittest
from mockupdb import MockupDB, going
import pytest
try:
from mockupdb import MockupDB, going
_HAVE_MOCKUPDB = True
except ImportError:
_HAVE_MOCKUPDB = False
from pymongo import MongoClient
pytestmark = pytest.mark.mockupdb
class TestMaxStalenessMongos(unittest.TestCase):
def test_mongos(self):

View File

@ -19,11 +19,21 @@ import time
import unittest
from queue import Queue
from mockupdb import MockupDB, go
import pytest
try:
from mockupdb import MockupDB, go
_HAVE_MOCKUPDB = True
except ImportError:
_HAVE_MOCKUPDB = False
from operations import upgrades # type: ignore[import]
from pymongo import MongoClient
pytestmark = pytest.mark.mockupdb
class TestMixedVersionSharded(unittest.TestCase):
def setup_server(self, upgrade):

View File

@ -16,7 +16,15 @@ from __future__ import annotations
import itertools
import unittest
from mockupdb import MockupDB, OpMsg, going
import pytest
try:
from mockupdb import MockupDB, OpMsg, going
_HAVE_MOCKUPDB = True
except ImportError:
_HAVE_MOCKUPDB = False
from operations import operations # type: ignore[import]
from pymongo import MongoClient, ReadPreference
@ -26,6 +34,8 @@ from pymongo.read_preferences import (
read_pref_mode_from_name,
)
pytestmark = pytest.mark.mockupdb
class TestMongosCommandReadMode(unittest.TestCase):
def test_aggregate(self):

View File

@ -15,12 +15,22 @@ from __future__ import annotations
import unittest
from mockupdb import Future, MockupDB, OpReply, going, wait_until
import pytest
try:
from mockupdb import Future, MockupDB, OpReply, going, wait_until
_HAVE_MOCKUPDB = True
except ImportError:
_HAVE_MOCKUPDB = False
from pymongo import MongoClient
from pymongo.errors import ConnectionFailure
from pymongo.topology_description import TOPOLOGY_TYPE
pytestmark = pytest.mark.mockupdb
class TestNetworkDisconnectPrimary(unittest.TestCase):
def test_network_disconnect_primary(self):

View File

@ -16,246 +16,261 @@ from __future__ import annotations
import unittest
from collections import namedtuple
from mockupdb import OP_MSG_FLAGS, MockupDB, OpMsg, OpMsgReply, going
import pytest
try:
from mockupdb import OP_MSG_FLAGS, MockupDB, OpMsg, OpMsgReply, going
_HAVE_MOCKUPDB = True
except ImportError:
_HAVE_MOCKUPDB = False
from pymongo import MongoClient, WriteConcern
from pymongo.cursor_shared import CursorType
from pymongo.operations import DeleteOne, InsertOne, UpdateOne
pytestmark = pytest.mark.mockupdb
Operation = namedtuple("Operation", ["name", "function", "request", "reply"])
operations = [
Operation(
"find_one",
lambda coll: coll.find_one({}),
request=OpMsg({"find": "coll"}, flags=0),
reply={"ok": 1, "cursor": {"firstBatch": [], "id": 0}},
),
Operation(
"aggregate",
lambda coll: coll.aggregate([]),
request=OpMsg({"aggregate": "coll"}, flags=0),
reply={"ok": 1, "cursor": {"firstBatch": [], "id": 0}},
),
Operation(
"insert_one",
lambda coll: coll.insert_one({}),
request=OpMsg({"insert": "coll"}, flags=0),
reply={"ok": 1, "n": 1},
),
Operation(
"insert_one-w0",
lambda coll: coll.with_options(write_concern=WriteConcern(w=0)).insert_one({}),
request=OpMsg({"insert": "coll"}, flags=OP_MSG_FLAGS["moreToCome"]),
reply=None,
),
Operation(
"insert_many",
lambda coll: coll.insert_many([{}, {}, {}]),
request=OpMsg({"insert": "coll"}, flags=0),
reply={"ok": 1, "n": 3},
),
Operation(
"insert_many-w0",
lambda coll: coll.with_options(write_concern=WriteConcern(w=0)).insert_many([{}, {}, {}]),
request=OpMsg({"insert": "coll"}, flags=0),
reply={"ok": 1, "n": 3},
),
Operation(
"insert_many-w0-unordered",
lambda coll: coll.with_options(write_concern=WriteConcern(w=0)).insert_many(
[{}, {}, {}], ordered=False
if _HAVE_MOCKUPDB:
operations = [
Operation(
"find_one",
lambda coll: coll.find_one({}),
request=OpMsg({"find": "coll"}, flags=0),
reply={"ok": 1, "cursor": {"firstBatch": [], "id": 0}},
),
request=OpMsg({"insert": "coll"}, flags=OP_MSG_FLAGS["moreToCome"]),
reply=None,
),
Operation(
"replace_one",
lambda coll: coll.replace_one({"_id": 1}, {"new": 1}),
request=OpMsg({"update": "coll"}, flags=0),
reply={"ok": 1, "n": 1, "nModified": 1},
),
Operation(
"replace_one-w0",
lambda coll: coll.with_options(write_concern=WriteConcern(w=0)).replace_one(
{"_id": 1}, {"new": 1}
Operation(
"aggregate",
lambda coll: coll.aggregate([]),
request=OpMsg({"aggregate": "coll"}, flags=0),
reply={"ok": 1, "cursor": {"firstBatch": [], "id": 0}},
),
request=OpMsg({"update": "coll"}, flags=OP_MSG_FLAGS["moreToCome"]),
reply=None,
),
Operation(
"update_one",
lambda coll: coll.update_one({"_id": 1}, {"$set": {"new": 1}}),
request=OpMsg({"update": "coll"}, flags=0),
reply={"ok": 1, "n": 1, "nModified": 1},
),
Operation(
"replace_one-w0",
lambda coll: coll.with_options(write_concern=WriteConcern(w=0)).update_one(
{"_id": 1}, {"$set": {"new": 1}}
Operation(
"insert_one",
lambda coll: coll.insert_one({}),
request=OpMsg({"insert": "coll"}, flags=0),
reply={"ok": 1, "n": 1},
),
request=OpMsg({"update": "coll"}, flags=OP_MSG_FLAGS["moreToCome"]),
reply=None,
),
Operation(
"update_many",
lambda coll: coll.update_many({"_id": 1}, {"$set": {"new": 1}}),
request=OpMsg({"update": "coll"}, flags=0),
reply={"ok": 1, "n": 1, "nModified": 1},
),
Operation(
"update_many-w0",
lambda coll: coll.with_options(write_concern=WriteConcern(w=0)).update_many(
{"_id": 1}, {"$set": {"new": 1}}
Operation(
"insert_one-w0",
lambda coll: coll.with_options(write_concern=WriteConcern(w=0)).insert_one({}),
request=OpMsg({"insert": "coll"}, flags=OP_MSG_FLAGS["moreToCome"]),
reply=None,
),
request=OpMsg({"update": "coll"}, flags=OP_MSG_FLAGS["moreToCome"]),
reply=None,
),
Operation(
"delete_one",
lambda coll: coll.delete_one({"a": 1}),
request=OpMsg({"delete": "coll"}, flags=0),
reply={"ok": 1, "n": 1},
),
Operation(
"delete_one-w0",
lambda coll: coll.with_options(write_concern=WriteConcern(w=0)).delete_one({"a": 1}),
request=OpMsg({"delete": "coll"}, flags=OP_MSG_FLAGS["moreToCome"]),
reply=None,
),
Operation(
"delete_many",
lambda coll: coll.delete_many({"a": 1}),
request=OpMsg({"delete": "coll"}, flags=0),
reply={"ok": 1, "n": 1},
),
Operation(
"delete_many-w0",
lambda coll: coll.with_options(write_concern=WriteConcern(w=0)).delete_many({"a": 1}),
request=OpMsg({"delete": "coll"}, flags=OP_MSG_FLAGS["moreToCome"]),
reply=None,
),
# Legacy methods
Operation(
"bulk_write_insert",
lambda coll: coll.bulk_write([InsertOne[dict]({}), InsertOne[dict]({})]),
request=OpMsg({"insert": "coll"}, flags=0),
reply={"ok": 1, "n": 2},
),
Operation(
"bulk_write_insert-w0",
lambda coll: coll.with_options(write_concern=WriteConcern(w=0)).bulk_write(
[InsertOne[dict]({}), InsertOne[dict]({})]
Operation(
"insert_many",
lambda coll: coll.insert_many([{}, {}, {}]),
request=OpMsg({"insert": "coll"}, flags=0),
reply={"ok": 1, "n": 3},
),
request=OpMsg({"insert": "coll"}, flags=0),
reply={"ok": 1, "n": 2},
),
Operation(
"bulk_write_insert-w0-unordered",
lambda coll: coll.with_options(write_concern=WriteConcern(w=0)).bulk_write(
[InsertOne[dict]({}), InsertOne[dict]({})], ordered=False
Operation(
"insert_many-w0",
lambda coll: coll.with_options(write_concern=WriteConcern(w=0)).insert_many(
[{}, {}, {}]
),
request=OpMsg({"insert": "coll"}, flags=0),
reply={"ok": 1, "n": 3},
),
request=OpMsg({"insert": "coll"}, flags=OP_MSG_FLAGS["moreToCome"]),
reply=None,
),
Operation(
"bulk_write_update",
lambda coll: coll.bulk_write(
[
UpdateOne({"_id": 1}, {"$set": {"new": 1}}),
UpdateOne({"_id": 2}, {"$set": {"new": 1}}),
]
Operation(
"insert_many-w0-unordered",
lambda coll: coll.with_options(write_concern=WriteConcern(w=0)).insert_many(
[{}, {}, {}], ordered=False
),
request=OpMsg({"insert": "coll"}, flags=OP_MSG_FLAGS["moreToCome"]),
reply=None,
),
request=OpMsg({"update": "coll"}, flags=0),
reply={"ok": 1, "n": 2, "nModified": 2},
),
Operation(
"bulk_write_update-w0",
lambda coll: coll.with_options(write_concern=WriteConcern(w=0)).bulk_write(
[
UpdateOne({"_id": 1}, {"$set": {"new": 1}}),
UpdateOne({"_id": 2}, {"$set": {"new": 1}}),
]
Operation(
"replace_one",
lambda coll: coll.replace_one({"_id": 1}, {"new": 1}),
request=OpMsg({"update": "coll"}, flags=0),
reply={"ok": 1, "n": 1, "nModified": 1},
),
request=OpMsg({"update": "coll"}, flags=0),
reply={"ok": 1, "n": 2, "nModified": 2},
),
Operation(
"bulk_write_update-w0-unordered",
lambda coll: coll.with_options(write_concern=WriteConcern(w=0)).bulk_write(
[
UpdateOne({"_id": 1}, {"$set": {"new": 1}}),
UpdateOne({"_id": 2}, {"$set": {"new": 1}}),
],
ordered=False,
Operation(
"replace_one-w0",
lambda coll: coll.with_options(write_concern=WriteConcern(w=0)).replace_one(
{"_id": 1}, {"new": 1}
),
request=OpMsg({"update": "coll"}, flags=OP_MSG_FLAGS["moreToCome"]),
reply=None,
),
request=OpMsg({"update": "coll"}, flags=OP_MSG_FLAGS["moreToCome"]),
reply=None,
),
Operation(
"bulk_write_delete",
lambda coll: coll.bulk_write([DeleteOne({"_id": 1}), DeleteOne({"_id": 2})]),
request=OpMsg({"delete": "coll"}, flags=0),
reply={"ok": 1, "n": 2},
),
Operation(
"bulk_write_delete-w0",
lambda coll: coll.with_options(write_concern=WriteConcern(w=0)).bulk_write(
[DeleteOne({"_id": 1}), DeleteOne({"_id": 2})]
Operation(
"update_one",
lambda coll: coll.update_one({"_id": 1}, {"$set": {"new": 1}}),
request=OpMsg({"update": "coll"}, flags=0),
reply={"ok": 1, "n": 1, "nModified": 1},
),
request=OpMsg({"delete": "coll"}, flags=0),
reply={"ok": 1, "n": 2},
),
Operation(
"bulk_write_delete-w0-unordered",
lambda coll: coll.with_options(write_concern=WriteConcern(w=0)).bulk_write(
[DeleteOne({"_id": 1}), DeleteOne({"_id": 2})], ordered=False
Operation(
"replace_one-w0",
lambda coll: coll.with_options(write_concern=WriteConcern(w=0)).update_one(
{"_id": 1}, {"$set": {"new": 1}}
),
request=OpMsg({"update": "coll"}, flags=OP_MSG_FLAGS["moreToCome"]),
reply=None,
),
request=OpMsg({"delete": "coll"}, flags=OP_MSG_FLAGS["moreToCome"]),
reply=None,
),
]
Operation(
"update_many",
lambda coll: coll.update_many({"_id": 1}, {"$set": {"new": 1}}),
request=OpMsg({"update": "coll"}, flags=0),
reply={"ok": 1, "n": 1, "nModified": 1},
),
Operation(
"update_many-w0",
lambda coll: coll.with_options(write_concern=WriteConcern(w=0)).update_many(
{"_id": 1}, {"$set": {"new": 1}}
),
request=OpMsg({"update": "coll"}, flags=OP_MSG_FLAGS["moreToCome"]),
reply=None,
),
Operation(
"delete_one",
lambda coll: coll.delete_one({"a": 1}),
request=OpMsg({"delete": "coll"}, flags=0),
reply={"ok": 1, "n": 1},
),
Operation(
"delete_one-w0",
lambda coll: coll.with_options(write_concern=WriteConcern(w=0)).delete_one({"a": 1}),
request=OpMsg({"delete": "coll"}, flags=OP_MSG_FLAGS["moreToCome"]),
reply=None,
),
Operation(
"delete_many",
lambda coll: coll.delete_many({"a": 1}),
request=OpMsg({"delete": "coll"}, flags=0),
reply={"ok": 1, "n": 1},
),
Operation(
"delete_many-w0",
lambda coll: coll.with_options(write_concern=WriteConcern(w=0)).delete_many({"a": 1}),
request=OpMsg({"delete": "coll"}, flags=OP_MSG_FLAGS["moreToCome"]),
reply=None,
),
# Legacy methods
Operation(
"bulk_write_insert",
lambda coll: coll.bulk_write([InsertOne[dict]({}), InsertOne[dict]({})]),
request=OpMsg({"insert": "coll"}, flags=0),
reply={"ok": 1, "n": 2},
),
Operation(
"bulk_write_insert-w0",
lambda coll: coll.with_options(write_concern=WriteConcern(w=0)).bulk_write(
[InsertOne[dict]({}), InsertOne[dict]({})]
),
request=OpMsg({"insert": "coll"}, flags=0),
reply={"ok": 1, "n": 2},
),
Operation(
"bulk_write_insert-w0-unordered",
lambda coll: coll.with_options(write_concern=WriteConcern(w=0)).bulk_write(
[InsertOne[dict]({}), InsertOne[dict]({})], ordered=False
),
request=OpMsg({"insert": "coll"}, flags=OP_MSG_FLAGS["moreToCome"]),
reply=None,
),
Operation(
"bulk_write_update",
lambda coll: coll.bulk_write(
[
UpdateOne({"_id": 1}, {"$set": {"new": 1}}),
UpdateOne({"_id": 2}, {"$set": {"new": 1}}),
]
),
request=OpMsg({"update": "coll"}, flags=0),
reply={"ok": 1, "n": 2, "nModified": 2},
),
Operation(
"bulk_write_update-w0",
lambda coll: coll.with_options(write_concern=WriteConcern(w=0)).bulk_write(
[
UpdateOne({"_id": 1}, {"$set": {"new": 1}}),
UpdateOne({"_id": 2}, {"$set": {"new": 1}}),
]
),
request=OpMsg({"update": "coll"}, flags=0),
reply={"ok": 1, "n": 2, "nModified": 2},
),
Operation(
"bulk_write_update-w0-unordered",
lambda coll: coll.with_options(write_concern=WriteConcern(w=0)).bulk_write(
[
UpdateOne({"_id": 1}, {"$set": {"new": 1}}),
UpdateOne({"_id": 2}, {"$set": {"new": 1}}),
],
ordered=False,
),
request=OpMsg({"update": "coll"}, flags=OP_MSG_FLAGS["moreToCome"]),
reply=None,
),
Operation(
"bulk_write_delete",
lambda coll: coll.bulk_write([DeleteOne({"_id": 1}), DeleteOne({"_id": 2})]),
request=OpMsg({"delete": "coll"}, flags=0),
reply={"ok": 1, "n": 2},
),
Operation(
"bulk_write_delete-w0",
lambda coll: coll.with_options(write_concern=WriteConcern(w=0)).bulk_write(
[DeleteOne({"_id": 1}), DeleteOne({"_id": 2})]
),
request=OpMsg({"delete": "coll"}, flags=0),
reply={"ok": 1, "n": 2},
),
Operation(
"bulk_write_delete-w0-unordered",
lambda coll: coll.with_options(write_concern=WriteConcern(w=0)).bulk_write(
[DeleteOne({"_id": 1}), DeleteOne({"_id": 2})], ordered=False
),
request=OpMsg({"delete": "coll"}, flags=OP_MSG_FLAGS["moreToCome"]),
reply=None,
),
]
operations_312 = [
Operation(
"find_raw_batches",
lambda coll: list(coll.find_raw_batches({})),
request=[
OpMsg({"find": "coll"}, flags=0),
OpMsg({"getMore": 7}, flags=0),
],
reply=[
{"ok": 1, "cursor": {"firstBatch": [{}], "id": 7}},
{"ok": 1, "cursor": {"nextBatch": [{}], "id": 0}},
],
),
Operation(
"aggregate_raw_batches",
lambda coll: list(coll.aggregate_raw_batches([])),
request=[
OpMsg({"aggregate": "coll"}, flags=0),
OpMsg({"getMore": 7}, flags=0),
],
reply=[
{"ok": 1, "cursor": {"firstBatch": [], "id": 7}},
{"ok": 1, "cursor": {"nextBatch": [{}], "id": 0}},
],
),
Operation(
"find_exhaust_cursor",
lambda coll: list(coll.find({}, cursor_type=CursorType.EXHAUST)),
request=[
OpMsg({"find": "coll"}, flags=0),
OpMsg({"getMore": 7}, flags=1 << 16),
],
reply=[
OpMsgReply({"ok": 1, "cursor": {"firstBatch": [{}], "id": 7}}, flags=0),
OpMsgReply({"ok": 1, "cursor": {"nextBatch": [{}], "id": 7}}, flags=2),
OpMsgReply({"ok": 1, "cursor": {"nextBatch": [{}], "id": 7}}, flags=2),
OpMsgReply({"ok": 1, "cursor": {"nextBatch": [{}], "id": 0}}, flags=0),
],
),
]
operations_312 = [
Operation(
"find_raw_batches",
lambda coll: list(coll.find_raw_batches({})),
request=[
OpMsg({"find": "coll"}, flags=0),
OpMsg({"getMore": 7}, flags=0),
],
reply=[
{"ok": 1, "cursor": {"firstBatch": [{}], "id": 7}},
{"ok": 1, "cursor": {"nextBatch": [{}], "id": 0}},
],
),
Operation(
"aggregate_raw_batches",
lambda coll: list(coll.aggregate_raw_batches([])),
request=[
OpMsg({"aggregate": "coll"}, flags=0),
OpMsg({"getMore": 7}, flags=0),
],
reply=[
{"ok": 1, "cursor": {"firstBatch": [], "id": 7}},
{"ok": 1, "cursor": {"nextBatch": [{}], "id": 0}},
],
),
Operation(
"find_exhaust_cursor",
lambda coll: list(coll.find({}, cursor_type=CursorType.EXHAUST)),
request=[
OpMsg({"find": "coll"}, flags=0),
OpMsg({"getMore": 7}, flags=1 << 16),
],
reply=[
OpMsgReply({"ok": 1, "cursor": {"firstBatch": [{}], "id": 7}}, flags=0),
OpMsgReply({"ok": 1, "cursor": {"nextBatch": [{}], "id": 7}}, flags=2),
OpMsgReply({"ok": 1, "cursor": {"nextBatch": [{}], "id": 7}}, flags=2),
OpMsgReply({"ok": 1, "cursor": {"nextBatch": [{}], "id": 0}}, flags=0),
],
),
]
else:
operations = []
operations_312 = []
class TestOpMsg(unittest.TestCase):

View File

@ -18,7 +18,15 @@ import itertools
import unittest
from typing import Any
from mockupdb import CommandBase, MockupDB, going
import pytest
try:
from mockupdb import CommandBase, MockupDB, going
_HAVE_MOCKUPDB = True
except ImportError:
_HAVE_MOCKUPDB = False
from operations import operations # type: ignore[import]
from pymongo import MongoClient, ReadPreference
@ -28,6 +36,8 @@ from pymongo.read_preferences import (
read_pref_mode_from_name,
)
pytestmark = pytest.mark.mockupdb
class OpMsgReadPrefBase(unittest.TestCase):
single_mongod = False

View File

@ -17,7 +17,15 @@ from __future__ import annotations
import unittest
from mockupdb import MockupDB, OpMsg, going
import pytest
try:
from mockupdb import MockupDB, OpMsg, going
_HAVE_MOCKUPDB = True
except ImportError:
_HAVE_MOCKUPDB = False
from bson import SON
from pymongo import MongoClient
@ -29,6 +37,8 @@ from pymongo.read_preferences import (
SecondaryPreferred,
)
pytestmark = pytest.mark.mockupdb
class TestQueryAndReadModeSharded(unittest.TestCase):
def test_query_and_read_mode_sharded_op_msg(self):

View File

@ -17,7 +17,16 @@ import itertools
import time
import unittest
from mockupdb import MockupDB, going, wait_until
import pytest
try:
from mockupdb import MockupDB, going, wait_until
_HAVE_MOCKUPDB = True
except ImportError:
_HAVE_MOCKUPDB = False
from operations import operations # type: ignore[import]
from pymongo import MongoClient
@ -25,6 +34,8 @@ from pymongo.errors import ConnectionFailure
from pymongo.operations import _Op
from pymongo.server_type import SERVER_TYPE
pytestmark = pytest.mark.mockupdb
class TestResetAndRequestCheck(unittest.TestCase):
def __init__(self, *args, **kwargs):

View File

@ -18,11 +18,21 @@ from __future__ import annotations
import datetime
import unittest
from mockupdb import MockupDB, going
import pytest
try:
from mockupdb import MockupDB, going
_HAVE_MOCKUPDB = True
except ImportError:
_HAVE_MOCKUPDB = False
from pymongo import MongoClient
from pymongo.errors import ServerSelectionTimeoutError
pytestmark = pytest.mark.mockupdb
class TestRSGhost(unittest.TestCase):
def test_rsghost(self):

View File

@ -20,11 +20,21 @@ from __future__ import annotations
import unittest
from mockupdb import MockupDB, going
import pytest
try:
from mockupdb import MockupDB, going
_HAVE_MOCKUPDB = True
except ImportError:
_HAVE_MOCKUPDB = False
from operations import operations # type: ignore[import]
from pymongo import MongoClient
pytestmark = pytest.mark.mockupdb
class TestSlaveOkayRS(unittest.TestCase):
def setup_server(self):

View File

@ -24,12 +24,22 @@ import itertools
import unittest
from queue import Queue
from mockupdb import MockupDB, going
import pytest
try:
from mockupdb import MockupDB, going
_HAVE_MOCKUPDB = True
except ImportError:
_HAVE_MOCKUPDB = False
from operations import operations # type: ignore[import]
from pymongo import MongoClient
from pymongo.read_preferences import make_read_preference, read_pref_mode_from_name
pytestmark = pytest.mark.mockupdb
class TestSlaveOkaySharded(unittest.TestCase):
def setup_server(self):

View File

@ -23,13 +23,23 @@ from __future__ import annotations
import itertools
import unittest
from mockupdb import MockupDB, going
import pytest
try:
from mockupdb import MockupDB, going
_HAVE_MOCKUPDB = True
except ImportError:
_HAVE_MOCKUPDB = False
from operations import operations # type: ignore[import]
from pymongo import MongoClient
from pymongo.read_preferences import make_read_preference, read_pref_mode_from_name
from pymongo.topology_description import TOPOLOGY_TYPE
pytestmark = pytest.mark.mockupdb
def topology_type_name(client):
topology_type = client._topology._description.topology_type

View File

@ -17,11 +17,21 @@ from __future__ import annotations
import unittest
from mockupdb import MockupDB, going
import pytest
try:
from mockupdb import MockupDB, going
_HAVE_MOCKUPDB = True
except ImportError:
_HAVE_MOCKUPDB = False
from pymongo import MongoClient
from pymongo.errors import OperationFailure
pytestmark = pytest.mark.mockupdb
class TestStandaloneShard(unittest.TestCase):
# See PYTHON-2048 and SERVER-44591.

View File

@ -39,73 +39,76 @@ from bson.objectid import ObjectId
from bson.regex import Regex
from pymongo.synchronous.mongo_client import MongoClient
# Ensure the C extensions are installed.
assert bson.has_c()
assert pymongo.has_c()
OPTS: CodecOptions[dict] = CodecOptions(
uuid_representation=STANDARD, datetime_conversion=DatetimeConversion.DATETIME_AUTO
)
client: MongoClient[dict] = MongoClient()
# Use a unique collection name for each process:
coll_name = f"test-{uuid.uuid4()}"
collection = client.test.get_collection(coll_name, codec_options=OPTS)
ndocs = 20
collection.drop()
doc = {
"int32": 2 << 15,
"int64": 2 << 50,
"null": None,
"bool": True,
"float": 1.5,
"str": "string",
"list": [1, 2, 3],
"dict": {"a": 1, "b": 2, "c": 3},
"datetime": datetime.datetime.fromtimestamp(1690328577.446),
"datetime_ms_out_of_range": DatetimeMS(-2 << 60),
"regex_native": re.compile("regex*"),
"regex_pymongo": Regex("regex*"),
"binary": Binary(b"bytes", 128),
"oid": ObjectId(),
"dbref": DBRef("test", 1),
"code": Code("function(){ return true; }"),
"code_w_scope": Code("return function(){ return x; }", scope={"x": False}),
"bytes": b"bytes",
"uuid": uuid.uuid4(),
}
collection.insert_many([dict(i=i, **doc) for i in range(ndocs)])
client.close() # Discard main thread's request socket.
client = MongoClient()
collection = client.test.get_collection(coll_name, codec_options=OPTS)
try:
from mod_wsgi import version as mod_wsgi_version # type: ignore[import]
_HAVE_MOD_WSGI = True
except:
mod_wsgi_version = None
_HAVE_MOD_WSGI = False
if _HAVE_MOD_WSGI:
# Ensure the C extensions are installed.
assert bson.has_c()
assert pymongo.has_c()
def application(environ, start_response):
results = list(collection.find().batch_size(10))
assert len(results) == ndocs, f"n_actual={len(results)} n_expected={ndocs}"
# Test encoding and decoding works (for sub interpreter support).
decoded = bson.decode(bson.encode(doc, codec_options=OPTS), codec_options=OPTS)
for key, value in doc.items():
# Native regex objects are decoded as bson Regex.
if isinstance(value, re.Pattern):
value = Regex.from_native(value)
assert decoded[key] == value, f"failed on doc[{key!r}]: {decoded[key]!r} != {value!r}"
assert isinstance(
decoded[key], type(value)
), f"failed on doc[{key}]: {decoded[key]!r} is not an instance of {type(value)}"
output = (
f" python {sys.version}, mod_wsgi {mod_wsgi_version},"
f" pymongo {pymongo.version},"
f' mod_wsgi.process_group = {environ["mod_wsgi.process_group"]!r}'
f' mod_wsgi.application_group = {environ["mod_wsgi.application_group"]!r}'
f' wsgi.multithread = {environ["wsgi.multithread"]!r}'
"\n"
OPTS: CodecOptions[dict] = CodecOptions(
uuid_representation=STANDARD, datetime_conversion=DatetimeConversion.DATETIME_AUTO
)
response_headers = [("Content-Length", str(len(output)))]
start_response("200 OK", response_headers)
return [output.encode("ascii")]
client: MongoClient[dict] = MongoClient()
# Use a unique collection name for each process:
coll_name = f"test-{uuid.uuid4()}"
collection = client.test.get_collection(coll_name, codec_options=OPTS)
ndocs = 20
collection.drop()
doc = {
"int32": 2 << 15,
"int64": 2 << 50,
"null": None,
"bool": True,
"float": 1.5,
"str": "string",
"list": [1, 2, 3],
"dict": {"a": 1, "b": 2, "c": 3},
"datetime": datetime.datetime.fromtimestamp(1690328577.446),
"datetime_ms_out_of_range": DatetimeMS(-2 << 60),
"regex_native": re.compile("regex*"),
"regex_pymongo": Regex("regex*"),
"binary": Binary(b"bytes", 128),
"oid": ObjectId(),
"dbref": DBRef("test", 1),
"code": Code("function(){ return true; }"),
"code_w_scope": Code("return function(){ return x; }", scope={"x": False}),
"bytes": b"bytes",
"uuid": uuid.uuid4(),
}
collection.insert_many([dict(i=i, **doc) for i in range(ndocs)])
client.close() # Discard main thread's request socket.
client = MongoClient()
collection = client.test.get_collection(coll_name, codec_options=OPTS)
def application(environ, start_response):
results = list(collection.find().batch_size(10))
assert len(results) == ndocs, f"n_actual={len(results)} n_expected={ndocs}"
# Test encoding and decoding works (for sub interpreter support).
decoded = bson.decode(bson.encode(doc, codec_options=OPTS), codec_options=OPTS)
for key, value in doc.items():
# Native regex objects are decoded as bson Regex.
if isinstance(value, re.Pattern):
value = Regex.from_native(value)
assert decoded[key] == value, f"failed on doc[{key!r}]: {decoded[key]!r} != {value!r}"
assert isinstance(
decoded[key], type(value)
), f"failed on doc[{key}]: {decoded[key]!r} is not an instance of {type(value)}"
output = (
f" python {sys.version}, mod_wsgi {mod_wsgi_version},"
f" pymongo {pymongo.version},"
f' mod_wsgi.process_group = {environ["mod_wsgi.process_group"]!r}'
f' mod_wsgi.application_group = {environ["mod_wsgi.application_group"]!r}'
f' wsgi.multithread = {environ["wsgi.multithread"]!r}'
"\n"
)
response_headers = [("Content-Length", str(len(output)))]
start_response("200 OK", response_headers)
return [output.encode("ascii")]

View File

@ -20,11 +20,16 @@ import os
import sys
import unittest
import pytest
sys.path[0:0] = [""]
import pymongo
from pymongo.errors import ServerSelectionTimeoutError
pytestmark = pytest.mark.ocsp
CA_FILE = os.environ.get("CA_FILE")
OCSP_TLS_SHOULD_SUCCEED = os.environ.get("OCSP_TLS_SHOULD_SUCCEED") == "true"

View File

@ -48,6 +48,8 @@ import time
import warnings
from typing import Any, List, Optional
import pytest
try:
import simplejson as json
except ImportError:
@ -61,6 +63,8 @@ from bson import decode, encode, json_util
from gridfs import GridFSBucket
from pymongo import MongoClient
pytestmark = pytest.mark.perf
# Spec says to use at least 1 minute cumulative execution time and up to 100 iterations or 5 minutes but that
# makes the benchmarks too slow. Instead, we use at least 30 seconds and at most 60 seconds.
NUM_ITERATIONS = 100

View File

@ -18,6 +18,8 @@ from __future__ import annotations
import os
import sys
import pytest
sys.path[0:0] = [""]
from test import IntegrationTest, client_context, unittest
@ -29,6 +31,9 @@ from test.utils import (
rs_or_single_client,
)
pytestmark = pytest.mark.data_lake
# Location of JSON test specifications.
_TEST_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "data_lake")

View File

@ -30,6 +30,8 @@ import warnings
from threading import Thread
from typing import Any, Dict, Mapping
import pytest
from pymongo.daemon import _spawn_daemon
from pymongo.synchronous.collection import Collection
@ -91,6 +93,8 @@ from pymongo.synchronous.encryption import Algorithm, ClientEncryption, QueryTyp
from pymongo.synchronous.mongo_client import MongoClient
from pymongo.write_concern import WriteConcern
pytestmark = pytest.mark.encryption
KMS_PROVIDERS = {"local": {"key": b"\x00" * 96}}

View File

@ -21,6 +21,8 @@ import time
import uuid
from typing import Any, Mapping
import pytest
sys.path[0:0] = [""]
from test import IntegrationTest, unittest
@ -33,6 +35,8 @@ from pymongo.operations import SearchIndexModel
from pymongo.read_concern import ReadConcern
from pymongo.write_concern import WriteConcern
pytestmark = pytest.mark.index_management
_TEST_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "index_management")
_NAME = "test-search-index"

View File

@ -20,12 +20,16 @@ import os
import sys
import threading
import pytest
sys.path[0:0] = [""]
from test import IntegrationTest, client_context, unittest
from test.unified_format import generate_test_classes
from test.utils import ExceptionCatchingThread, get_pool, rs_client, wait_until
pytestmark = pytest.mark.load_balancer
# Location of JSON test specifications.
TEST_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "load_balancer")

View File

@ -19,6 +19,8 @@ import os
import sys
import unittest
import pytest
sys.path[0:0] = [""]
from test import IntegrationTest, client_context
@ -26,6 +28,8 @@ from test import IntegrationTest, client_context
from bson.codec_options import CodecOptions
from pymongo.synchronous.encryption import _HAVE_PYMONGOCRYPT, ClientEncryption, EncryptionError
pytestmark = pytest.mark.csfle
class TestonDemandGCPCredentials(IntegrationTest):
@classmethod