Merge branch 'master' into dependabot/github_actions/actions-850ffb00e9
This commit is contained in:
commit
6845f98079
@ -1,64 +0,0 @@
|
|||||||
diff --git a/test/load_balancer/cursors.json b/test/load_balancer/cursors.json
|
|
||||||
index 43e4fbb4f..4e2a55fd4 100644
|
|
||||||
--- a/test/load_balancer/cursors.json
|
|
||||||
+++ b/test/load_balancer/cursors.json
|
|
||||||
@@ -376,7 +376,7 @@
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
+ "description": "pinned connections are not returned after an network error during getMore",
|
|
||||||
- "description": "pinned connections are returned after an network error during getMore",
|
|
||||||
"operations": [
|
|
||||||
{
|
|
||||||
"name": "failPoint",
|
|
||||||
@@ -440,7 +440,7 @@
|
|
||||||
"object": "testRunner",
|
|
||||||
"arguments": {
|
|
||||||
"client": "client0",
|
|
||||||
+ "connections": 1
|
|
||||||
- "connections": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
@@ -659,7 +659,7 @@
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
+ "description": "pinned connections are not returned to the pool after a non-network error on getMore",
|
|
||||||
- "description": "pinned connections are returned to the pool after a non-network error on getMore",
|
|
||||||
"operations": [
|
|
||||||
{
|
|
||||||
"name": "failPoint",
|
|
||||||
@@ -715,7 +715,7 @@
|
|
||||||
"object": "testRunner",
|
|
||||||
"arguments": {
|
|
||||||
"client": "client0",
|
|
||||||
+ "connections": 1
|
|
||||||
- "connections": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
diff --git a/test/load_balancer/sdam-error-handling.json b/test/load_balancer/sdam-error-handling.json
|
|
||||||
index 63aabc04d..462fa0aac 100644
|
|
||||||
--- a/test/load_balancer/sdam-error-handling.json
|
|
||||||
+++ b/test/load_balancer/sdam-error-handling.json
|
|
||||||
@@ -366,6 +366,9 @@
|
|
||||||
{
|
|
||||||
"connectionCreatedEvent": {}
|
|
||||||
},
|
|
||||||
+ {
|
|
||||||
+ "poolClearedEvent": {}
|
|
||||||
+ },
|
|
||||||
{
|
|
||||||
"connectionClosedEvent": {
|
|
||||||
"reason": "error"
|
|
||||||
@@ -378,9 +375,6 @@
|
|
||||||
"connectionCheckOutFailedEvent": {
|
|
||||||
"reason": "connectionError"
|
|
||||||
}
|
|
||||||
- },
|
|
||||||
- {
|
|
||||||
- "poolClearedEvent": {}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
diff --git a/test/discovery_and_monitoring/unified/serverMonitoringMode.json b/test/discovery_and_monitoring/unified/serverMonitoringMode.json
|
|
||||||
index e44fad1b..4b492f7d 100644
|
|
||||||
--- a/test/discovery_and_monitoring/unified/serverMonitoringMode.json
|
|
||||||
+++ b/test/discovery_and_monitoring/unified/serverMonitoringMode.json
|
|
||||||
@@ -5,7 +5,8 @@
|
|
||||||
{
|
|
||||||
"topologies": [
|
|
||||||
"single",
|
|
||||||
- "sharded"
|
|
||||||
+ "sharded",
|
|
||||||
+ "sharded-replicaset"
|
|
||||||
],
|
|
||||||
"serverless": "forbid"
|
|
||||||
}
|
|
||||||
@ -1,61 +0,0 @@
|
|||||||
diff --git a/test/server_selection_logging/replica-set.json b/test/server_selection_logging/replica-set.json
|
|
||||||
index 830b1ea51..5eba784bf 100644
|
|
||||||
--- a/test/server_selection_logging/replica-set.json
|
|
||||||
+++ b/test/server_selection_logging/replica-set.json
|
|
||||||
@@ -184,7 +184,7 @@
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
- "level": "debug",
|
|
||||||
+ "level": "info",
|
|
||||||
"component": "serverSelection",
|
|
||||||
"data": {
|
|
||||||
"message": "Waiting for suitable server to become available",
|
|
||||||
diff --git a/test/server_selection_logging/standalone.json b/test/server_selection_logging/standalone.json
|
|
||||||
index 830b1ea51..5eba784bf 100644
|
|
||||||
--- a/test/server_selection_logging/standalone.json
|
|
||||||
+++ b/test/server_selection_logging/standalone.json
|
|
||||||
@@ -191,7 +191,7 @@
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
- "level": "debug",
|
|
||||||
+ "level": "info",
|
|
||||||
"component": "serverSelection",
|
|
||||||
"data": {
|
|
||||||
"message": "Waiting for suitable server to become available",
|
|
||||||
diff --git a/test/server_selection_logging/sharded.json b/test/server_selection_logging/sharded.json
|
|
||||||
index 830b1ea51..5eba784bf 100644
|
|
||||||
--- a/test/server_selection_logging/sharded.json
|
|
||||||
+++ b/test/server_selection_logging/sharded.json
|
|
||||||
@@ -193,7 +193,7 @@
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
- "level": "debug",
|
|
||||||
+ "level": "info",
|
|
||||||
"component": "serverSelection",
|
|
||||||
"data": {
|
|
||||||
"message": "Waiting for suitable server to become available",
|
|
||||||
diff --git a/test/server_selection_logging/sharded.json b/test/server_selection_logging/operation-id.json
|
|
||||||
index 830b1ea51..5eba784bf 100644
|
|
||||||
--- a/test/server_selection_logging/operation-id.json
|
|
||||||
+++ b/test/server_selection_logging/operation-id.json
|
|
||||||
@@ -197,7 +197,7 @@
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
- "level": "debug",
|
|
||||||
+ "level": "info",
|
|
||||||
"component": "serverSelection",
|
|
||||||
"data": {
|
|
||||||
"message": "Waiting for suitable server to become available",
|
|
||||||
@@ -383,7 +383,7 @@
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
- "level": "debug",
|
|
||||||
+ "level": "info",
|
|
||||||
"component": "serverSelection",
|
|
||||||
"data": {
|
|
||||||
"message": "Waiting for suitable server to become available",
|
|
||||||
@ -1,31 +0,0 @@
|
|||||||
diff --git a/test/discovery_and_monitoring/errors/error_handling_handshake.json b/test/discovery_and_monitoring/errors/error_handling_handshake.json
|
|
||||||
index 56ca7d113..bf83f46f6 100644
|
|
||||||
--- a/test/discovery_and_monitoring/errors/error_handling_handshake.json
|
|
||||||
+++ b/test/discovery_and_monitoring/errors/error_handling_handshake.json
|
|
||||||
@@ -97,14 +97,22 @@
|
|
||||||
"outcome": {
|
|
||||||
"servers": {
|
|
||||||
"a:27017": {
|
|
||||||
- "type": "Unknown",
|
|
||||||
- "topologyVersion": null,
|
|
||||||
+ "type": "RSPrimary",
|
|
||||||
+ "setName": "rs",
|
|
||||||
+ "topologyVersion": {
|
|
||||||
+ "processId": {
|
|
||||||
+ "$oid": "000000000000000000000001"
|
|
||||||
+ },
|
|
||||||
+ "counter": {
|
|
||||||
+ "$numberLong": "1"
|
|
||||||
+ }
|
|
||||||
+ },
|
|
||||||
"pool": {
|
|
||||||
- "generation": 1
|
|
||||||
+ "generation": 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
- "topologyType": "ReplicaSetNoPrimary",
|
|
||||||
+ "topologyType": "ReplicaSetWithPrimary",
|
|
||||||
"logicalSessionTimeoutMinutes": null,
|
|
||||||
"setName": "rs"
|
|
||||||
}
|
|
||||||
19
justfile
19
justfile
@ -16,64 +16,78 @@ default:
|
|||||||
resync:
|
resync:
|
||||||
@uv sync --quiet
|
@uv sync --quiet
|
||||||
|
|
||||||
|
# Set up the development environment
|
||||||
install:
|
install:
|
||||||
bash .evergreen/scripts/setup-dev-env.sh
|
bash .evergreen/scripts/setup-dev-env.sh
|
||||||
|
|
||||||
|
# Build the HTML documentation
|
||||||
[group('docs')]
|
[group('docs')]
|
||||||
docs: && resync
|
docs: && resync
|
||||||
{{docs_run}} sphinx-build -W -b html doc {{doc_build}}/html
|
{{docs_run}} sphinx-build -W -b html doc {{doc_build}}/html
|
||||||
|
|
||||||
|
# Serve the docs locally with live-reload
|
||||||
[group('docs')]
|
[group('docs')]
|
||||||
docs-serve: && resync
|
docs-serve: && resync
|
||||||
{{docs_run}} sphinx-autobuild -W -b html doc --watch ./pymongo --watch ./bson --watch ./gridfs {{doc_build}}/serve
|
{{docs_run}} sphinx-autobuild -W -b html doc --watch ./pymongo --watch ./bson --watch ./gridfs {{doc_build}}/serve
|
||||||
|
|
||||||
|
# Check documentation hyperlinks for broken URLs
|
||||||
[group('docs')]
|
[group('docs')]
|
||||||
docs-linkcheck: && resync
|
docs-linkcheck: && resync
|
||||||
{{docs_run}} sphinx-build -E -b linkcheck doc {{doc_build}}/linkcheck
|
{{docs_run}} sphinx-build -E -b linkcheck doc {{doc_build}}/linkcheck
|
||||||
|
|
||||||
|
# Run mypy and pyright
|
||||||
[group('typing')]
|
[group('typing')]
|
||||||
typing: && resync
|
typing: && resync
|
||||||
just typing-mypy
|
just typing-mypy
|
||||||
just typing-pyright
|
just typing-pyright
|
||||||
|
|
||||||
|
# Run mypy against the library source and test suite
|
||||||
[group('typing')]
|
[group('typing')]
|
||||||
typing-mypy: && resync
|
typing-mypy: && resync
|
||||||
{{typing_run}} python -m mypy {{mypy_args}} bson gridfs tools pymongo
|
{{typing_run}} python -m mypy {{mypy_args}} bson gridfs tools pymongo
|
||||||
{{typing_run}} python -m mypy {{mypy_args}} --config-file mypy_test.ini test
|
{{typing_run}} python -m mypy {{mypy_args}} --config-file mypy_test.ini test
|
||||||
{{typing_run}} python -m mypy {{mypy_args}} test/test_typing.py test/test_typing_strict.py
|
{{typing_run}} python -m mypy {{mypy_args}} test/test_typing.py test/test_typing_strict.py
|
||||||
|
|
||||||
|
# Run pyright against the typing test files
|
||||||
[group('typing')]
|
[group('typing')]
|
||||||
typing-pyright: && resync
|
typing-pyright: && resync
|
||||||
{{typing_run}} python -m pyright test/test_typing.py test/test_typing_strict.py
|
{{typing_run}} python -m pyright test/test_typing.py test/test_typing_strict.py
|
||||||
{{typing_run}} python -m pyright -p strict_pyrightconfig.json test/test_typing_strict.py
|
{{typing_run}} python -m pyright -p strict_pyrightconfig.json test/test_typing_strict.py
|
||||||
|
|
||||||
|
# Run all pre-commit hooks across the repository
|
||||||
[group('lint')]
|
[group('lint')]
|
||||||
lint *args="": && resync
|
lint *args="": && resync
|
||||||
uvx pre-commit run --all-files {{args}}
|
uvx pre-commit run --all-files {{args}}
|
||||||
|
|
||||||
|
# Run shellcheck, doc8, and slotscheck
|
||||||
[group('lint')]
|
[group('lint')]
|
||||||
lint-manual *args="": && resync
|
lint-manual *args="": && resync
|
||||||
uvx pre-commit run --all-files --hook-stage manual {{args}}
|
uvx pre-commit run --all-files --hook-stage manual {{args}}
|
||||||
|
|
||||||
|
# Run pytest (e.g. just test test/test_uri_parser.py)
|
||||||
[group('test')]
|
[group('test')]
|
||||||
test *args="-v --durations=5 --maxfail=10": && resync
|
test *args="-v --durations=5 --maxfail=10": && resync
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
uv run ${USE_ACTIVE_VENV:+--active} --extra test python -m pytest {{args}}
|
uv run ${USE_ACTIVE_VENV:+--active} --extra test python -m pytest {{args}}
|
||||||
|
|
||||||
|
# Run the BSON test suite with numpy
|
||||||
[group('test')]
|
[group('test')]
|
||||||
test-numpy *args="": && resync
|
test-numpy *args="": && resync
|
||||||
just setup-tests numpy {{args}}
|
just setup-tests numpy {{args}}
|
||||||
just run-tests test/test_bson.py
|
just run-tests test/test_bson.py
|
||||||
|
|
||||||
|
# Run tests via the Evergreen test runner script
|
||||||
[group('test')]
|
[group('test')]
|
||||||
run-tests *args: && resync
|
run-tests *args: && resync
|
||||||
bash ./.evergreen/run-tests.sh {{args}}
|
bash ./.evergreen/run-tests.sh {{args}}
|
||||||
|
|
||||||
|
# Set up the test environment (auth, TLS, etc.)
|
||||||
[group('test')]
|
[group('test')]
|
||||||
setup-tests *args="":
|
setup-tests *args="":
|
||||||
bash .evergreen/scripts/setup-tests.sh {{args}}
|
bash .evergreen/scripts/setup-tests.sh {{args}}
|
||||||
|
|
||||||
|
# Tear down resources created by setup-tests
|
||||||
[group('test')]
|
[group('test')]
|
||||||
teardown-tests:
|
teardown-tests:
|
||||||
bash .evergreen/scripts/teardown-tests.sh
|
bash .evergreen/scripts/teardown-tests.sh
|
||||||
@ -82,25 +96,30 @@ teardown-tests:
|
|||||||
integration-tests:
|
integration-tests:
|
||||||
bash integration_tests/run.sh
|
bash integration_tests/run.sh
|
||||||
|
|
||||||
|
# Run the full test suite with coverage
|
||||||
[group('test')]
|
[group('test')]
|
||||||
test-coverage *args="":
|
test-coverage *args="":
|
||||||
just setup-tests --cov
|
just setup-tests --cov
|
||||||
just run-tests {{args}}
|
just run-tests {{args}}
|
||||||
|
|
||||||
|
# Print the coverage summary to the terminal
|
||||||
[group('coverage')]
|
[group('coverage')]
|
||||||
coverage-report:
|
coverage-report:
|
||||||
uv tool run --with "coverage[toml]" coverage report
|
uv tool run --with "coverage[toml]" coverage report
|
||||||
|
|
||||||
|
# Generate an HTML coverage report in htmlcov/
|
||||||
[group('coverage')]
|
[group('coverage')]
|
||||||
coverage-html:
|
coverage-html:
|
||||||
uv tool run --with "coverage[toml]" coverage html
|
uv tool run --with "coverage[toml]" coverage html
|
||||||
@echo "Coverage report generated in htmlcov/index.html"
|
@echo "Coverage report generated in htmlcov/index.html"
|
||||||
|
|
||||||
|
# Generate an XML coverage report at coverage.xml
|
||||||
[group('coverage')]
|
[group('coverage')]
|
||||||
coverage-xml:
|
coverage-xml:
|
||||||
uv tool run --with "coverage[toml]" coverage xml
|
uv tool run --with "coverage[toml]" coverage xml
|
||||||
@echo "Coverage report generated in coverage.xml"
|
@echo "Coverage report generated in coverage.xml"
|
||||||
|
|
||||||
|
# Start a MongoDB server via drivers-evergreen-tools
|
||||||
[group('server')]
|
[group('server')]
|
||||||
run-server *args="":
|
run-server *args="":
|
||||||
bash .evergreen/scripts/run-server.sh {{args}}
|
bash .evergreen/scripts/run-server.sh {{args}}
|
||||||
|
|||||||
@ -3326,6 +3326,7 @@ class TestAutomaticDecryptionKeys(AsyncEncryptionIntegrationTest):
|
|||||||
class TestExplicitTextEncryptionProse(AsyncEncryptionIntegrationTest):
|
class TestExplicitTextEncryptionProse(AsyncEncryptionIntegrationTest):
|
||||||
@async_client_context.require_no_standalone
|
@async_client_context.require_no_standalone
|
||||||
@async_client_context.require_version_min(8, 2, -1)
|
@async_client_context.require_version_min(8, 2, -1)
|
||||||
|
@async_client_context.require_version_max(8, 99, 99)
|
||||||
@async_client_context.require_libmongocrypt_min(1, 15, 1)
|
@async_client_context.require_libmongocrypt_min(1, 15, 1)
|
||||||
@async_client_context.require_pymongocrypt_min(1, 16, 0)
|
@async_client_context.require_pymongocrypt_min(1, 16, 0)
|
||||||
async def asyncSetUp(self):
|
async def asyncSetUp(self):
|
||||||
|
|||||||
@ -42,6 +42,91 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"tests": [
|
"tests": [
|
||||||
|
{
|
||||||
|
"description": "disambiguatedPaths is not present when showExpandedEvents is false/unset",
|
||||||
|
"runOnRequirements": [
|
||||||
|
{
|
||||||
|
"minServerVersion": "6.1.0",
|
||||||
|
"maxServerVersion": "8.1.99",
|
||||||
|
"topologies": [
|
||||||
|
"replicaset",
|
||||||
|
"load-balanced",
|
||||||
|
"sharded"
|
||||||
|
],
|
||||||
|
"serverless": "forbid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"minServerVersion": "8.2.1",
|
||||||
|
"topologies": [
|
||||||
|
"replicaset",
|
||||||
|
"load-balanced",
|
||||||
|
"sharded"
|
||||||
|
],
|
||||||
|
"serverless": "forbid"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"operations": [
|
||||||
|
{
|
||||||
|
"name": "insertOne",
|
||||||
|
"object": "collection0",
|
||||||
|
"arguments": {
|
||||||
|
"document": {
|
||||||
|
"_id": 1,
|
||||||
|
"a": {
|
||||||
|
"1": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "createChangeStream",
|
||||||
|
"object": "collection0",
|
||||||
|
"arguments": {
|
||||||
|
"pipeline": []
|
||||||
|
},
|
||||||
|
"saveResultAsEntity": "changeStream0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "updateOne",
|
||||||
|
"object": "collection0",
|
||||||
|
"arguments": {
|
||||||
|
"filter": {
|
||||||
|
"_id": 1
|
||||||
|
},
|
||||||
|
"update": {
|
||||||
|
"$set": {
|
||||||
|
"a.1": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "iterateUntilDocumentOrError",
|
||||||
|
"object": "changeStream0",
|
||||||
|
"expectResult": {
|
||||||
|
"operationType": "update",
|
||||||
|
"ns": {
|
||||||
|
"db": "database0",
|
||||||
|
"coll": "collection0"
|
||||||
|
},
|
||||||
|
"updateDescription": {
|
||||||
|
"updatedFields": {
|
||||||
|
"$$exists": true
|
||||||
|
},
|
||||||
|
"removedFields": {
|
||||||
|
"$$exists": true
|
||||||
|
},
|
||||||
|
"truncatedArrays": {
|
||||||
|
"$$exists": true
|
||||||
|
},
|
||||||
|
"disambiguatedPaths": {
|
||||||
|
"$$exists": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"description": "disambiguatedPaths is present on updateDescription when an ambiguous path is present",
|
"description": "disambiguatedPaths is present on updateDescription when an ambiguous path is present",
|
||||||
"operations": [
|
"operations": [
|
||||||
|
|||||||
@ -63,47 +63,6 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"description": "nsType is present when creating timeseries",
|
|
||||||
"operations": [
|
|
||||||
{
|
|
||||||
"name": "dropCollection",
|
|
||||||
"object": "database0",
|
|
||||||
"arguments": {
|
|
||||||
"collection": "foo"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "createChangeStream",
|
|
||||||
"object": "database0",
|
|
||||||
"arguments": {
|
|
||||||
"pipeline": [],
|
|
||||||
"showExpandedEvents": true
|
|
||||||
},
|
|
||||||
"saveResultAsEntity": "changeStream0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "createCollection",
|
|
||||||
"object": "database0",
|
|
||||||
"arguments": {
|
|
||||||
"collection": "foo",
|
|
||||||
"timeseries": {
|
|
||||||
"timeField": "time",
|
|
||||||
"metaField": "meta",
|
|
||||||
"granularity": "minutes"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "iterateUntilDocumentOrError",
|
|
||||||
"object": "changeStream0",
|
|
||||||
"expectResult": {
|
|
||||||
"operationType": "create",
|
|
||||||
"nsType": "timeseries"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"description": "nsType is present when creating views",
|
"description": "nsType is present when creating views",
|
||||||
"operations": [
|
"operations": [
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
"runOnRequirements": [
|
"runOnRequirements": [
|
||||||
{
|
{
|
||||||
"minServerVersion": "8.2.0",
|
"minServerVersion": "8.2.0",
|
||||||
|
"maxServerVersion": "8.99.99",
|
||||||
"topologies": [
|
"topologies": [
|
||||||
"replicaset",
|
"replicaset",
|
||||||
"sharded",
|
"sharded",
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
"runOnRequirements": [
|
"runOnRequirements": [
|
||||||
{
|
{
|
||||||
"minServerVersion": "8.2.0",
|
"minServerVersion": "8.2.0",
|
||||||
|
"maxServerVersion": "8.99.99",
|
||||||
"topologies": [
|
"topologies": [
|
||||||
"replicaset",
|
"replicaset",
|
||||||
"sharded",
|
"sharded",
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
"runOnRequirements": [
|
"runOnRequirements": [
|
||||||
{
|
{
|
||||||
"minServerVersion": "8.2.0",
|
"minServerVersion": "8.2.0",
|
||||||
|
"maxServerVersion": "8.99.99",
|
||||||
"topologies": [
|
"topologies": [
|
||||||
"replicaset",
|
"replicaset",
|
||||||
"sharded",
|
"sharded",
|
||||||
|
|||||||
@ -126,7 +126,7 @@
|
|||||||
],
|
],
|
||||||
"tests": [
|
"tests": [
|
||||||
{
|
{
|
||||||
"description": "Insert QE suffixPreview",
|
"description": "Insert QE substringPreview",
|
||||||
"operations": [
|
"operations": [
|
||||||
{
|
{
|
||||||
"name": "insertOne",
|
"name": "insertOne",
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
"runOnRequirements": [
|
"runOnRequirements": [
|
||||||
{
|
{
|
||||||
"minServerVersion": "8.2.0",
|
"minServerVersion": "8.2.0",
|
||||||
|
"maxServerVersion": "8.99.99",
|
||||||
"topologies": [
|
"topologies": [
|
||||||
"replicaset",
|
"replicaset",
|
||||||
"sharded",
|
"sharded",
|
||||||
|
|||||||
@ -0,0 +1,485 @@
|
|||||||
|
{
|
||||||
|
"description": "fle2v2-InsertFind-keyAltName",
|
||||||
|
"schemaVersion": "1.25",
|
||||||
|
"runOnRequirements": [
|
||||||
|
{
|
||||||
|
"minServerVersion": "7.0.0",
|
||||||
|
"topologies": [
|
||||||
|
"replicaset",
|
||||||
|
"sharded",
|
||||||
|
"load-balanced"
|
||||||
|
],
|
||||||
|
"csfle": {
|
||||||
|
"minLibmongocryptVersion": "1.18.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"createEntities": [
|
||||||
|
{
|
||||||
|
"client": {
|
||||||
|
"id": "client0",
|
||||||
|
"autoEncryptOpts": {
|
||||||
|
"keyVaultNamespace": "keyvault.datakeys",
|
||||||
|
"kmsProviders": {
|
||||||
|
"local": {
|
||||||
|
"key": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"encryptedFieldsMap": {
|
||||||
|
"default.default": {
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"path": "encryptedIndexed",
|
||||||
|
"bsonType": "string",
|
||||||
|
"queries": {
|
||||||
|
"queryType": "equality",
|
||||||
|
"contention": {
|
||||||
|
"$numberLong": "0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"keyAltName": "altname"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"observeEvents": [
|
||||||
|
"commandStartedEvent"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"database": {
|
||||||
|
"id": "db",
|
||||||
|
"client": "client0",
|
||||||
|
"databaseName": "default"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"collection": {
|
||||||
|
"id": "coll",
|
||||||
|
"database": "db",
|
||||||
|
"collectionName": "default"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"client": {
|
||||||
|
"id": "client_unencrypted",
|
||||||
|
"observeEvents": [
|
||||||
|
"commandStartedEvent"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"database": {
|
||||||
|
"id": "db_unencrypted",
|
||||||
|
"client": "client_unencrypted",
|
||||||
|
"databaseName": "default"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"collection": {
|
||||||
|
"id": "coll_unencrypted",
|
||||||
|
"database": "db_unencrypted",
|
||||||
|
"collectionName": "default"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"initialData": [
|
||||||
|
{
|
||||||
|
"databaseName": "default",
|
||||||
|
"collectionName": "default",
|
||||||
|
"documents": [],
|
||||||
|
"createOptions": {
|
||||||
|
"encryptedFields": {
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"keyId": {
|
||||||
|
"$binary": {
|
||||||
|
"base64": "EjRWeBI0mHYSNBI0VniQEg==",
|
||||||
|
"subType": "04"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"path": "encryptedIndexed",
|
||||||
|
"bsonType": "string",
|
||||||
|
"queries": {
|
||||||
|
"queryType": "equality",
|
||||||
|
"contention": {
|
||||||
|
"$numberLong": "0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"databaseName": "keyvault",
|
||||||
|
"collectionName": "datakeys",
|
||||||
|
"documents": [
|
||||||
|
{
|
||||||
|
"_id": {
|
||||||
|
"$binary": {
|
||||||
|
"base64": "EjRWeBI0mHYSNBI0VniQEg==",
|
||||||
|
"subType": "04"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"keyMaterial": {
|
||||||
|
"$binary": {
|
||||||
|
"base64": "sHe0kz57YW7v8g9VP9sf/+K1ex4JqKc5rf/URX3n3p8XdZ6+15uXPaSayC6adWbNxkFskuMCOifDoTT+rkqMtFkDclOy884RuGGtUysq3X7zkAWYTKi8QAfKkajvVbZl2y23UqgVasdQu3OVBQCrH/xY00nNAs/52e958nVjBuzQkSb1T8pKJAyjZsHJ60+FtnfafDZSTAIBJYn7UWBCwQ==",
|
||||||
|
"subType": "00"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"creationDate": {
|
||||||
|
"$date": {
|
||||||
|
"$numberLong": "1648914851981"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"updateDate": {
|
||||||
|
"$date": {
|
||||||
|
"$numberLong": "1648914851981"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"$numberInt": "0"
|
||||||
|
},
|
||||||
|
"masterKey": {
|
||||||
|
"provider": "local"
|
||||||
|
},
|
||||||
|
"keyAltNames": [
|
||||||
|
"altname"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tests": [
|
||||||
|
{
|
||||||
|
"description": "Insert and find FLE2 indexed field",
|
||||||
|
"operations": [
|
||||||
|
{
|
||||||
|
"name": "insertOne",
|
||||||
|
"arguments": {
|
||||||
|
"document": {
|
||||||
|
"_id": 1,
|
||||||
|
"encryptedIndexed": "123"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"object": "coll"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "find",
|
||||||
|
"arguments": {
|
||||||
|
"filter": {
|
||||||
|
"encryptedIndexed": "123"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"object": "coll",
|
||||||
|
"expectResult": [
|
||||||
|
{
|
||||||
|
"_id": 1,
|
||||||
|
"encryptedIndexed": "123"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "find",
|
||||||
|
"object": "coll_unencrypted",
|
||||||
|
"arguments": {
|
||||||
|
"filter": {}
|
||||||
|
},
|
||||||
|
"expectResult": [
|
||||||
|
{
|
||||||
|
"_id": 1,
|
||||||
|
"encryptedIndexed": {
|
||||||
|
"$$type": "binData"
|
||||||
|
},
|
||||||
|
"__safeContent__": [
|
||||||
|
{
|
||||||
|
"$binary": {
|
||||||
|
"base64": "31eCYlbQoVboc5zwC8IoyJVSkag9PxREka8dkmbXJeY=",
|
||||||
|
"subType": "00"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"expectEvents": [
|
||||||
|
{
|
||||||
|
"client": "client0",
|
||||||
|
"events": [
|
||||||
|
{
|
||||||
|
"commandStartedEvent": {
|
||||||
|
"command": {
|
||||||
|
"find": "datakeys",
|
||||||
|
"filter": {
|
||||||
|
"$or": [
|
||||||
|
{
|
||||||
|
"_id": {
|
||||||
|
"$in": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"keyAltNames": {
|
||||||
|
"$in": [
|
||||||
|
"altname"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"$db": "keyvault",
|
||||||
|
"readConcern": {
|
||||||
|
"level": "majority"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"commandName": "find"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"commandStartedEvent": {
|
||||||
|
"command": {
|
||||||
|
"insert": "default",
|
||||||
|
"documents": [
|
||||||
|
{
|
||||||
|
"_id": 1,
|
||||||
|
"encryptedIndexed": {
|
||||||
|
"$$type": "binData"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ordered": true,
|
||||||
|
"encryptionInformation": {
|
||||||
|
"type": 1,
|
||||||
|
"schema": {
|
||||||
|
"default.default": {
|
||||||
|
"escCollection": "enxcol_.default.esc",
|
||||||
|
"ecocCollection": "enxcol_.default.ecoc",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"keyId": {
|
||||||
|
"$binary": {
|
||||||
|
"base64": "EjRWeBI0mHYSNBI0VniQEg==",
|
||||||
|
"subType": "04"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"path": "encryptedIndexed",
|
||||||
|
"bsonType": "string",
|
||||||
|
"queries": {
|
||||||
|
"queryType": "equality",
|
||||||
|
"contention": {
|
||||||
|
"$numberLong": "0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"commandName": "insert"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"commandStartedEvent": {
|
||||||
|
"command": {
|
||||||
|
"find": "default",
|
||||||
|
"filter": {
|
||||||
|
"encryptedIndexed": {
|
||||||
|
"$eq": {
|
||||||
|
"$binary": {
|
||||||
|
"base64": "DIkAAAAFZAAgAAAAAPGmZcUzdE/FPILvRSyAScGvZparGI2y9rJ/vSBxgCujBXMAIAAAAACi1RjmndKqgnXy7xb22RzUbnZl1sOZRXPOC0KcJkAxmQVsACAAAAAApJtKPW4+o9B7gAynNLL26jtlB4+hq5TXResijcYet8USY20AAAAAAAAAAAAA",
|
||||||
|
"subType": "06"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"encryptionInformation": {
|
||||||
|
"type": 1,
|
||||||
|
"schema": {
|
||||||
|
"default.default": {
|
||||||
|
"escCollection": "enxcol_.default.esc",
|
||||||
|
"ecocCollection": "enxcol_.default.ecoc",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"keyId": {
|
||||||
|
"$binary": {
|
||||||
|
"base64": "EjRWeBI0mHYSNBI0VniQEg==",
|
||||||
|
"subType": "04"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"path": "encryptedIndexed",
|
||||||
|
"bsonType": "string",
|
||||||
|
"queries": {
|
||||||
|
"queryType": "equality",
|
||||||
|
"contention": {
|
||||||
|
"$numberLong": "0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"commandName": "find"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Create translates keyAltName",
|
||||||
|
"operations": [
|
||||||
|
{
|
||||||
|
"name": "dropCollection",
|
||||||
|
"object": "db",
|
||||||
|
"arguments": {
|
||||||
|
"collection": "default"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "createCollection",
|
||||||
|
"object": "db",
|
||||||
|
"arguments": {
|
||||||
|
"collection": "default"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"expectEvents": [
|
||||||
|
{
|
||||||
|
"client": "client0",
|
||||||
|
"events": [
|
||||||
|
{
|
||||||
|
"commandStartedEvent": {
|
||||||
|
"command": {
|
||||||
|
"drop": "enxcol_.default.esc"
|
||||||
|
},
|
||||||
|
"commandName": "drop"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"commandStartedEvent": {
|
||||||
|
"command": {
|
||||||
|
"drop": "enxcol_.default.ecoc"
|
||||||
|
},
|
||||||
|
"commandName": "drop"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"commandStartedEvent": {
|
||||||
|
"command": {
|
||||||
|
"drop": "default"
|
||||||
|
},
|
||||||
|
"commandName": "drop"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"commandStartedEvent": {
|
||||||
|
"command": {
|
||||||
|
"create": "enxcol_.default.esc",
|
||||||
|
"clusteredIndex": {
|
||||||
|
"key": {
|
||||||
|
"_id": 1
|
||||||
|
},
|
||||||
|
"unique": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"commandName": "create"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"commandStartedEvent": {
|
||||||
|
"command": {
|
||||||
|
"create": "enxcol_.default.ecoc",
|
||||||
|
"clusteredIndex": {
|
||||||
|
"key": {
|
||||||
|
"_id": 1
|
||||||
|
},
|
||||||
|
"unique": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"commandName": "create"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"commandStartedEvent": {
|
||||||
|
"command": {
|
||||||
|
"find": "datakeys",
|
||||||
|
"filter": {
|
||||||
|
"$or": [
|
||||||
|
{
|
||||||
|
"_id": {
|
||||||
|
"$in": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"keyAltNames": {
|
||||||
|
"$in": [
|
||||||
|
"altname"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"$db": "keyvault",
|
||||||
|
"readConcern": {
|
||||||
|
"level": "majority"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"commandName": "find"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"commandStartedEvent": {
|
||||||
|
"command": {
|
||||||
|
"create": "default",
|
||||||
|
"encryptedFields": {
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"path": "encryptedIndexed",
|
||||||
|
"bsonType": "string",
|
||||||
|
"queries": {
|
||||||
|
"queryType": "equality",
|
||||||
|
"contention": {
|
||||||
|
"$numberLong": "0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"keyId": {
|
||||||
|
"$binary": {
|
||||||
|
"base64": "EjRWeBI0mHYSNBI0VniQEg==",
|
||||||
|
"subType": "04"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"commandName": "create"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"commandStartedEvent": {
|
||||||
|
"command": {
|
||||||
|
"createIndexes": "default",
|
||||||
|
"indexes": [
|
||||||
|
{
|
||||||
|
"name": "__safeContent___1",
|
||||||
|
"key": {
|
||||||
|
"__safeContent__": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"commandName": "createIndexes"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -9,7 +9,9 @@
|
|||||||
],
|
],
|
||||||
"failPoint": {
|
"failPoint": {
|
||||||
"configureFailPoint": "failCommand",
|
"configureFailPoint": "failCommand",
|
||||||
"mode": "alwaysOn",
|
"mode": {
|
||||||
|
"times": 50
|
||||||
|
},
|
||||||
"data": {
|
"data": {
|
||||||
"failCommands": [
|
"failCommands": [
|
||||||
"isMaster",
|
"isMaster",
|
||||||
|
|||||||
@ -1,142 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "backpressure-network-error-fail-replicaset",
|
|
||||||
"schemaVersion": "1.17",
|
|
||||||
"runOnRequirements": [
|
|
||||||
{
|
|
||||||
"minServerVersion": "4.4",
|
|
||||||
"serverless": "forbid",
|
|
||||||
"topologies": [
|
|
||||||
"replicaset"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"createEntities": [
|
|
||||||
{
|
|
||||||
"client": {
|
|
||||||
"id": "setupClient",
|
|
||||||
"useMultipleMongoses": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"initialData": [
|
|
||||||
{
|
|
||||||
"collectionName": "backpressure-network-error-fail",
|
|
||||||
"databaseName": "sdam-tests",
|
|
||||||
"documents": [
|
|
||||||
{
|
|
||||||
"_id": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"_id": 2
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"tests": [
|
|
||||||
{
|
|
||||||
"description": "apply backpressure on network connection errors during connection establishment",
|
|
||||||
"operations": [
|
|
||||||
{
|
|
||||||
"name": "createEntities",
|
|
||||||
"object": "testRunner",
|
|
||||||
"arguments": {
|
|
||||||
"entities": [
|
|
||||||
{
|
|
||||||
"client": {
|
|
||||||
"id": "client",
|
|
||||||
"useMultipleMongoses": false,
|
|
||||||
"observeEvents": [
|
|
||||||
"serverDescriptionChangedEvent",
|
|
||||||
"poolClearedEvent"
|
|
||||||
],
|
|
||||||
"uriOptions": {
|
|
||||||
"retryWrites": false,
|
|
||||||
"heartbeatFrequencyMS": 1000000,
|
|
||||||
"serverMonitoringMode": "poll",
|
|
||||||
"appname": "backpressureNetworkErrorFailTest"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"database": {
|
|
||||||
"id": "database",
|
|
||||||
"client": "client",
|
|
||||||
"databaseName": "sdam-tests"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"collection": {
|
|
||||||
"id": "collection",
|
|
||||||
"database": "database",
|
|
||||||
"collectionName": "backpressure-network-error-fail"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "waitForEvent",
|
|
||||||
"object": "testRunner",
|
|
||||||
"arguments": {
|
|
||||||
"client": "client",
|
|
||||||
"event": {
|
|
||||||
"serverDescriptionChangedEvent": {
|
|
||||||
"newDescription": {
|
|
||||||
"type": "RSPrimary"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"count": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "failPoint",
|
|
||||||
"object": "testRunner",
|
|
||||||
"arguments": {
|
|
||||||
"client": "setupClient",
|
|
||||||
"failPoint": {
|
|
||||||
"configureFailPoint": "failCommand",
|
|
||||||
"mode": "alwaysOn",
|
|
||||||
"data": {
|
|
||||||
"failCommands": [
|
|
||||||
"isMaster",
|
|
||||||
"hello"
|
|
||||||
],
|
|
||||||
"appName": "backpressureNetworkErrorFailTest",
|
|
||||||
"closeConnection": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "insertMany",
|
|
||||||
"object": "collection",
|
|
||||||
"arguments": {
|
|
||||||
"documents": [
|
|
||||||
{
|
|
||||||
"_id": 3
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"_id": 4
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"expectError": {
|
|
||||||
"isError": true,
|
|
||||||
"errorLabelsContain": [
|
|
||||||
"SystemOverloadedError",
|
|
||||||
"RetryableError"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"expectEvents": [
|
|
||||||
{
|
|
||||||
"client": "client",
|
|
||||||
"eventType": "cmap",
|
|
||||||
"events": []
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -1,142 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "backpressure-network-error-fail-single",
|
|
||||||
"schemaVersion": "1.17",
|
|
||||||
"runOnRequirements": [
|
|
||||||
{
|
|
||||||
"minServerVersion": "4.4",
|
|
||||||
"serverless": "forbid",
|
|
||||||
"topologies": [
|
|
||||||
"single"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"createEntities": [
|
|
||||||
{
|
|
||||||
"client": {
|
|
||||||
"id": "setupClient",
|
|
||||||
"useMultipleMongoses": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"initialData": [
|
|
||||||
{
|
|
||||||
"collectionName": "backpressure-network-error-fail",
|
|
||||||
"databaseName": "sdam-tests",
|
|
||||||
"documents": [
|
|
||||||
{
|
|
||||||
"_id": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"_id": 2
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"tests": [
|
|
||||||
{
|
|
||||||
"description": "apply backpressure on network connection errors during connection establishment",
|
|
||||||
"operations": [
|
|
||||||
{
|
|
||||||
"name": "createEntities",
|
|
||||||
"object": "testRunner",
|
|
||||||
"arguments": {
|
|
||||||
"entities": [
|
|
||||||
{
|
|
||||||
"client": {
|
|
||||||
"id": "client",
|
|
||||||
"useMultipleMongoses": false,
|
|
||||||
"observeEvents": [
|
|
||||||
"serverDescriptionChangedEvent",
|
|
||||||
"poolClearedEvent"
|
|
||||||
],
|
|
||||||
"uriOptions": {
|
|
||||||
"retryWrites": false,
|
|
||||||
"heartbeatFrequencyMS": 1000000,
|
|
||||||
"serverMonitoringMode": "poll",
|
|
||||||
"appname": "backpressureNetworkErrorFailTest"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"database": {
|
|
||||||
"id": "database",
|
|
||||||
"client": "client",
|
|
||||||
"databaseName": "sdam-tests"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"collection": {
|
|
||||||
"id": "collection",
|
|
||||||
"database": "database",
|
|
||||||
"collectionName": "backpressure-network-error-fail"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "waitForEvent",
|
|
||||||
"object": "testRunner",
|
|
||||||
"arguments": {
|
|
||||||
"client": "client",
|
|
||||||
"event": {
|
|
||||||
"serverDescriptionChangedEvent": {
|
|
||||||
"newDescription": {
|
|
||||||
"type": "Standalone"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"count": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "failPoint",
|
|
||||||
"object": "testRunner",
|
|
||||||
"arguments": {
|
|
||||||
"client": "setupClient",
|
|
||||||
"failPoint": {
|
|
||||||
"configureFailPoint": "failCommand",
|
|
||||||
"mode": "alwaysOn",
|
|
||||||
"data": {
|
|
||||||
"failCommands": [
|
|
||||||
"isMaster",
|
|
||||||
"hello"
|
|
||||||
],
|
|
||||||
"appName": "backpressureNetworkErrorFailTest",
|
|
||||||
"closeConnection": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "insertMany",
|
|
||||||
"object": "collection",
|
|
||||||
"arguments": {
|
|
||||||
"documents": [
|
|
||||||
{
|
|
||||||
"_id": 3
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"_id": 4
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"expectError": {
|
|
||||||
"isError": true,
|
|
||||||
"errorLabelsContain": [
|
|
||||||
"SystemOverloadedError",
|
|
||||||
"RetryableError"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"expectEvents": [
|
|
||||||
{
|
|
||||||
"client": "client",
|
|
||||||
"eventType": "cmap",
|
|
||||||
"events": []
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -1,145 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "backpressure-network-timeout-error-replicaset",
|
|
||||||
"schemaVersion": "1.17",
|
|
||||||
"runOnRequirements": [
|
|
||||||
{
|
|
||||||
"minServerVersion": "4.4",
|
|
||||||
"serverless": "forbid",
|
|
||||||
"topologies": [
|
|
||||||
"replicaset"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"createEntities": [
|
|
||||||
{
|
|
||||||
"client": {
|
|
||||||
"id": "setupClient",
|
|
||||||
"useMultipleMongoses": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"initialData": [
|
|
||||||
{
|
|
||||||
"collectionName": "backpressure-network-timeout-error",
|
|
||||||
"databaseName": "sdam-tests",
|
|
||||||
"documents": [
|
|
||||||
{
|
|
||||||
"_id": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"_id": 2
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"tests": [
|
|
||||||
{
|
|
||||||
"description": "apply backpressure on network timeout error during connection establishment",
|
|
||||||
"operations": [
|
|
||||||
{
|
|
||||||
"name": "createEntities",
|
|
||||||
"object": "testRunner",
|
|
||||||
"arguments": {
|
|
||||||
"entities": [
|
|
||||||
{
|
|
||||||
"client": {
|
|
||||||
"id": "client",
|
|
||||||
"useMultipleMongoses": false,
|
|
||||||
"observeEvents": [
|
|
||||||
"serverDescriptionChangedEvent",
|
|
||||||
"poolClearedEvent"
|
|
||||||
],
|
|
||||||
"uriOptions": {
|
|
||||||
"retryWrites": false,
|
|
||||||
"heartbeatFrequencyMS": 1000000,
|
|
||||||
"appname": "backpressureNetworkTimeoutErrorTest",
|
|
||||||
"serverMonitoringMode": "poll",
|
|
||||||
"connectTimeoutMS": 250,
|
|
||||||
"socketTimeoutMS": 250
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"database": {
|
|
||||||
"id": "database",
|
|
||||||
"client": "client",
|
|
||||||
"databaseName": "sdam-tests"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"collection": {
|
|
||||||
"id": "collection",
|
|
||||||
"database": "database",
|
|
||||||
"collectionName": "backpressure-network-timeout-error"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "waitForEvent",
|
|
||||||
"object": "testRunner",
|
|
||||||
"arguments": {
|
|
||||||
"client": "client",
|
|
||||||
"event": {
|
|
||||||
"serverDescriptionChangedEvent": {
|
|
||||||
"newDescription": {
|
|
||||||
"type": "RSPrimary"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"count": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "failPoint",
|
|
||||||
"object": "testRunner",
|
|
||||||
"arguments": {
|
|
||||||
"client": "setupClient",
|
|
||||||
"failPoint": {
|
|
||||||
"configureFailPoint": "failCommand",
|
|
||||||
"mode": "alwaysOn",
|
|
||||||
"data": {
|
|
||||||
"failCommands": [
|
|
||||||
"isMaster",
|
|
||||||
"hello"
|
|
||||||
],
|
|
||||||
"blockConnection": true,
|
|
||||||
"blockTimeMS": 500,
|
|
||||||
"appName": "backpressureNetworkTimeoutErrorTest"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "insertMany",
|
|
||||||
"object": "collection",
|
|
||||||
"arguments": {
|
|
||||||
"documents": [
|
|
||||||
{
|
|
||||||
"_id": 3
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"_id": 4
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"expectError": {
|
|
||||||
"isError": true,
|
|
||||||
"errorLabelsContain": [
|
|
||||||
"SystemOverloadedError",
|
|
||||||
"RetryableError"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"expectEvents": [
|
|
||||||
{
|
|
||||||
"client": "client",
|
|
||||||
"eventType": "cmap",
|
|
||||||
"events": []
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -1,145 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "backpressure-network-timeout-error-single",
|
|
||||||
"schemaVersion": "1.17",
|
|
||||||
"runOnRequirements": [
|
|
||||||
{
|
|
||||||
"minServerVersion": "4.4",
|
|
||||||
"serverless": "forbid",
|
|
||||||
"topologies": [
|
|
||||||
"single"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"createEntities": [
|
|
||||||
{
|
|
||||||
"client": {
|
|
||||||
"id": "setupClient",
|
|
||||||
"useMultipleMongoses": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"initialData": [
|
|
||||||
{
|
|
||||||
"collectionName": "backpressure-network-timeout-error",
|
|
||||||
"databaseName": "sdam-tests",
|
|
||||||
"documents": [
|
|
||||||
{
|
|
||||||
"_id": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"_id": 2
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"tests": [
|
|
||||||
{
|
|
||||||
"description": "apply backpressure on network timeout error during connection establishment",
|
|
||||||
"operations": [
|
|
||||||
{
|
|
||||||
"name": "createEntities",
|
|
||||||
"object": "testRunner",
|
|
||||||
"arguments": {
|
|
||||||
"entities": [
|
|
||||||
{
|
|
||||||
"client": {
|
|
||||||
"id": "client",
|
|
||||||
"useMultipleMongoses": false,
|
|
||||||
"observeEvents": [
|
|
||||||
"serverDescriptionChangedEvent",
|
|
||||||
"poolClearedEvent"
|
|
||||||
],
|
|
||||||
"uriOptions": {
|
|
||||||
"retryWrites": false,
|
|
||||||
"heartbeatFrequencyMS": 1000000,
|
|
||||||
"appname": "backpressureNetworkTimeoutErrorTest",
|
|
||||||
"serverMonitoringMode": "poll",
|
|
||||||
"connectTimeoutMS": 250,
|
|
||||||
"socketTimeoutMS": 250
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"database": {
|
|
||||||
"id": "database",
|
|
||||||
"client": "client",
|
|
||||||
"databaseName": "sdam-tests"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"collection": {
|
|
||||||
"id": "collection",
|
|
||||||
"database": "database",
|
|
||||||
"collectionName": "backpressure-network-timeout-error"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "waitForEvent",
|
|
||||||
"object": "testRunner",
|
|
||||||
"arguments": {
|
|
||||||
"client": "client",
|
|
||||||
"event": {
|
|
||||||
"serverDescriptionChangedEvent": {
|
|
||||||
"newDescription": {
|
|
||||||
"type": "Standalone"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"count": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "failPoint",
|
|
||||||
"object": "testRunner",
|
|
||||||
"arguments": {
|
|
||||||
"client": "setupClient",
|
|
||||||
"failPoint": {
|
|
||||||
"configureFailPoint": "failCommand",
|
|
||||||
"mode": "alwaysOn",
|
|
||||||
"data": {
|
|
||||||
"failCommands": [
|
|
||||||
"isMaster",
|
|
||||||
"hello"
|
|
||||||
],
|
|
||||||
"blockConnection": true,
|
|
||||||
"blockTimeMS": 500,
|
|
||||||
"appName": "backpressureNetworkTimeoutErrorTest"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "insertMany",
|
|
||||||
"object": "collection",
|
|
||||||
"arguments": {
|
|
||||||
"documents": [
|
|
||||||
{
|
|
||||||
"_id": 3
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"_id": 4
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"expectError": {
|
|
||||||
"isError": true,
|
|
||||||
"errorLabelsContain": [
|
|
||||||
"SystemOverloadedError",
|
|
||||||
"RetryableError"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"expectEvents": [
|
|
||||||
{
|
|
||||||
"client": "client",
|
|
||||||
"eventType": "cmap",
|
|
||||||
"events": []
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -1,106 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "backpressure-server-description-unchanged-on-min-pool-size-population-error",
|
|
||||||
"schemaVersion": "1.17",
|
|
||||||
"runOnRequirements": [
|
|
||||||
{
|
|
||||||
"minServerVersion": "4.4",
|
|
||||||
"serverless": "forbid",
|
|
||||||
"topologies": [
|
|
||||||
"single"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"createEntities": [
|
|
||||||
{
|
|
||||||
"client": {
|
|
||||||
"id": "setupClient",
|
|
||||||
"useMultipleMongoses": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"tests": [
|
|
||||||
{
|
|
||||||
"description": "the server description is not changed on handshake error during minPoolSize population",
|
|
||||||
"operations": [
|
|
||||||
{
|
|
||||||
"name": "failPoint",
|
|
||||||
"object": "testRunner",
|
|
||||||
"arguments": {
|
|
||||||
"client": "setupClient",
|
|
||||||
"failPoint": {
|
|
||||||
"configureFailPoint": "failCommand",
|
|
||||||
"mode": {
|
|
||||||
"skip": 1
|
|
||||||
},
|
|
||||||
"data": {
|
|
||||||
"failCommands": [
|
|
||||||
"hello",
|
|
||||||
"isMaster"
|
|
||||||
],
|
|
||||||
"appName": "authErrorTest",
|
|
||||||
"closeConnection": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "createEntities",
|
|
||||||
"object": "testRunner",
|
|
||||||
"arguments": {
|
|
||||||
"entities": [
|
|
||||||
{
|
|
||||||
"client": {
|
|
||||||
"id": "client",
|
|
||||||
"observeEvents": [
|
|
||||||
"serverDescriptionChangedEvent",
|
|
||||||
"connectionClosedEvent"
|
|
||||||
],
|
|
||||||
"uriOptions": {
|
|
||||||
"appname": "authErrorTest",
|
|
||||||
"minPoolSize": 5,
|
|
||||||
"maxConnecting": 1,
|
|
||||||
"serverMonitoringMode": "poll",
|
|
||||||
"heartbeatFrequencyMS": 1000000
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "waitForEvent",
|
|
||||||
"object": "testRunner",
|
|
||||||
"arguments": {
|
|
||||||
"client": "client",
|
|
||||||
"event": {
|
|
||||||
"serverDescriptionChangedEvent": {}
|
|
||||||
},
|
|
||||||
"count": 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "waitForEvent",
|
|
||||||
"object": "testRunner",
|
|
||||||
"arguments": {
|
|
||||||
"client": "client",
|
|
||||||
"event": {
|
|
||||||
"connectionClosedEvent": {}
|
|
||||||
},
|
|
||||||
"count": 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"expectEvents": [
|
|
||||||
{
|
|
||||||
"client": "client",
|
|
||||||
"eventType": "sdam",
|
|
||||||
"events": [
|
|
||||||
{
|
|
||||||
"serverDescriptionChangedEvent": {}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -3308,6 +3308,7 @@ class TestAutomaticDecryptionKeys(EncryptionIntegrationTest):
|
|||||||
class TestExplicitTextEncryptionProse(EncryptionIntegrationTest):
|
class TestExplicitTextEncryptionProse(EncryptionIntegrationTest):
|
||||||
@client_context.require_no_standalone
|
@client_context.require_no_standalone
|
||||||
@client_context.require_version_min(8, 2, -1)
|
@client_context.require_version_min(8, 2, -1)
|
||||||
|
@client_context.require_version_max(8, 99, 99)
|
||||||
@client_context.require_libmongocrypt_min(1, 15, 1)
|
@client_context.require_libmongocrypt_min(1, 15, 1)
|
||||||
@client_context.require_pymongocrypt_min(1, 16, 0)
|
@client_context.require_pymongocrypt_min(1, 16, 0)
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
|||||||
271
test/test_pyopenssl_context.py
Normal file
271
test/test_pyopenssl_context.py
Normal file
@ -0,0 +1,271 @@
|
|||||||
|
# Copyright 2026-present MongoDB, Inc.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
"""Unit tests for pyopenssl_context.py.
|
||||||
|
|
||||||
|
These tests require PyOpenSSL (install via: pip install pymongo[ocsp]).
|
||||||
|
Tests are automatically skipped when PyOpenSSL is not available.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import ssl
|
||||||
|
import sys
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
sys.path[0:0] = [""]
|
||||||
|
|
||||||
|
from test import unittest
|
||||||
|
|
||||||
|
try:
|
||||||
|
from pymongo import pyopenssl_context as _ctx_module
|
||||||
|
from pymongo.pyopenssl_context import (
|
||||||
|
PROTOCOL_SSLv23,
|
||||||
|
SSLContext,
|
||||||
|
_is_ip_address,
|
||||||
|
_ragged_eof,
|
||||||
|
)
|
||||||
|
|
||||||
|
_HAVE_PYOPENSSL = True
|
||||||
|
except ImportError:
|
||||||
|
_HAVE_PYOPENSSL = False
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Pure functions (no SSL context required)
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
class TestIsIpAddress(unittest.TestCase):
|
||||||
|
@unittest.skipUnless(_HAVE_PYOPENSSL, "PyOpenSSL is not available.")
|
||||||
|
def test_ipv4(self):
|
||||||
|
self.assertTrue(_is_ip_address("192.168.1.1"))
|
||||||
|
|
||||||
|
@unittest.skipUnless(_HAVE_PYOPENSSL, "PyOpenSSL is not available.")
|
||||||
|
def test_ipv6(self):
|
||||||
|
self.assertTrue(_is_ip_address("::1"))
|
||||||
|
self.assertTrue(_is_ip_address("2001:db8::1"))
|
||||||
|
|
||||||
|
@unittest.skipUnless(_HAVE_PYOPENSSL, "PyOpenSSL is not available.")
|
||||||
|
def test_hostname_is_not_ip(self):
|
||||||
|
self.assertFalse(_is_ip_address("example.com"))
|
||||||
|
self.assertFalse(_is_ip_address("localhost"))
|
||||||
|
|
||||||
|
@unittest.skipUnless(_HAVE_PYOPENSSL, "PyOpenSSL is not available.")
|
||||||
|
def test_invalid_string_returns_false(self):
|
||||||
|
self.assertFalse(_is_ip_address("not-an-ip"))
|
||||||
|
|
||||||
|
@unittest.skipUnless(_HAVE_PYOPENSSL, "PyOpenSSL is not available.")
|
||||||
|
def test_unicode_error_returns_false(self):
|
||||||
|
# UnicodeError path: some inputs that can't be decoded.
|
||||||
|
# ip_address raises UnicodeError for byte strings with non-ASCII.
|
||||||
|
self.assertFalse(_is_ip_address(b"\xff\xfe"))
|
||||||
|
|
||||||
|
|
||||||
|
class TestRaggedEof(unittest.TestCase):
|
||||||
|
@unittest.skipUnless(_HAVE_PYOPENSSL, "PyOpenSSL is not available.")
|
||||||
|
def test_matching_args_returns_true(self):
|
||||||
|
from OpenSSL.SSL import SysCallError
|
||||||
|
|
||||||
|
exc = SysCallError(-1, "Unexpected EOF")
|
||||||
|
self.assertTrue(_ragged_eof(exc))
|
||||||
|
|
||||||
|
@unittest.skipUnless(_HAVE_PYOPENSSL, "PyOpenSSL is not available.")
|
||||||
|
def test_non_matching_args_returns_false(self):
|
||||||
|
from OpenSSL.SSL import SysCallError
|
||||||
|
|
||||||
|
exc = SysCallError(0, "something else")
|
||||||
|
self.assertFalse(_ragged_eof(exc))
|
||||||
|
|
||||||
|
@unittest.skipUnless(_HAVE_PYOPENSSL, "PyOpenSSL is not available.")
|
||||||
|
def test_wrong_code_returns_false(self):
|
||||||
|
from OpenSSL.SSL import SysCallError
|
||||||
|
|
||||||
|
exc = SysCallError(5, "Unexpected EOF")
|
||||||
|
self.assertFalse(_ragged_eof(exc))
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# SSLContext — construction and properties
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
class TestSSLContextConstruction(unittest.TestCase):
|
||||||
|
def _make(self):
|
||||||
|
return SSLContext(PROTOCOL_SSLv23)
|
||||||
|
|
||||||
|
@unittest.skipUnless(_HAVE_PYOPENSSL, "PyOpenSSL is not available.")
|
||||||
|
def test_protocol_property(self):
|
||||||
|
ctx = self._make()
|
||||||
|
self.assertEqual(ctx.protocol, PROTOCOL_SSLv23)
|
||||||
|
|
||||||
|
@unittest.skipUnless(_HAVE_PYOPENSSL, "PyOpenSSL is not available.")
|
||||||
|
def test_default_check_hostname(self):
|
||||||
|
ctx = self._make()
|
||||||
|
self.assertTrue(ctx.check_hostname)
|
||||||
|
|
||||||
|
@unittest.skipUnless(_HAVE_PYOPENSSL, "PyOpenSSL is not available.")
|
||||||
|
def test_set_check_hostname_false(self):
|
||||||
|
ctx = self._make()
|
||||||
|
ctx.check_hostname = False
|
||||||
|
self.assertFalse(ctx.check_hostname)
|
||||||
|
|
||||||
|
@unittest.skipUnless(_HAVE_PYOPENSSL, "PyOpenSSL is not available.")
|
||||||
|
def test_set_check_hostname_invalid_raises(self):
|
||||||
|
ctx = self._make()
|
||||||
|
with self.assertRaises(TypeError):
|
||||||
|
ctx.check_hostname = "yes"
|
||||||
|
|
||||||
|
@unittest.skipUnless(_HAVE_PYOPENSSL, "PyOpenSSL is not available.")
|
||||||
|
def test_default_check_ocsp_endpoint(self):
|
||||||
|
ctx = self._make()
|
||||||
|
self.assertTrue(ctx.check_ocsp_endpoint)
|
||||||
|
|
||||||
|
@unittest.skipUnless(_HAVE_PYOPENSSL, "PyOpenSSL is not available.")
|
||||||
|
def test_set_check_ocsp_endpoint_false(self):
|
||||||
|
ctx = self._make()
|
||||||
|
ctx.check_ocsp_endpoint = False
|
||||||
|
self.assertFalse(ctx.check_ocsp_endpoint)
|
||||||
|
|
||||||
|
@unittest.skipUnless(_HAVE_PYOPENSSL, "PyOpenSSL is not available.")
|
||||||
|
def test_verify_mode_roundtrip(self):
|
||||||
|
ctx = self._make()
|
||||||
|
ctx.verify_mode = ssl.CERT_REQUIRED
|
||||||
|
self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
|
||||||
|
|
||||||
|
@unittest.skipUnless(_HAVE_PYOPENSSL, "PyOpenSSL is not available.")
|
||||||
|
def test_verify_mode_cert_none(self):
|
||||||
|
ctx = self._make()
|
||||||
|
ctx.verify_mode = ssl.CERT_NONE
|
||||||
|
self.assertEqual(ctx.verify_mode, ssl.CERT_NONE)
|
||||||
|
|
||||||
|
@unittest.skipUnless(_HAVE_PYOPENSSL, "PyOpenSSL is not available.")
|
||||||
|
def test_options_setter_and_getter(self):
|
||||||
|
ctx = self._make()
|
||||||
|
from pymongo.pyopenssl_context import OP_NO_SSLv3
|
||||||
|
|
||||||
|
ctx.options = OP_NO_SSLv3
|
||||||
|
self.assertTrue(ctx.options & OP_NO_SSLv3)
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# SSLContext._load_certifi
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
class TestLoadCertifi(unittest.TestCase):
|
||||||
|
@unittest.skipUnless(_HAVE_PYOPENSSL, "PyOpenSSL is not available.")
|
||||||
|
def test_raises_when_certifi_unavailable(self):
|
||||||
|
from pymongo.errors import ConfigurationError
|
||||||
|
|
||||||
|
ctx = SSLContext(PROTOCOL_SSLv23)
|
||||||
|
with patch.object(_ctx_module, "_HAVE_CERTIFI", False):
|
||||||
|
with self.assertRaises(ConfigurationError) as exc_ctx:
|
||||||
|
ctx._load_certifi()
|
||||||
|
self.assertIn("certifi", str(exc_ctx.exception))
|
||||||
|
|
||||||
|
@unittest.skipUnless(_HAVE_PYOPENSSL, "PyOpenSSL is not available.")
|
||||||
|
def test_loads_when_certifi_available(self):
|
||||||
|
if not _ctx_module._HAVE_CERTIFI:
|
||||||
|
self.skipTest("certifi not installed")
|
||||||
|
ctx = SSLContext(PROTOCOL_SSLv23)
|
||||||
|
ctx.verify_mode = ssl.CERT_NONE
|
||||||
|
# Should not raise.
|
||||||
|
ctx._load_certifi()
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# SSLContext.load_default_certs — platform branching
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
class TestLoadDefaultCerts(unittest.TestCase):
|
||||||
|
@unittest.skipUnless(_HAVE_PYOPENSSL, "PyOpenSSL is not available.")
|
||||||
|
def test_darwin_calls_load_certifi(self):
|
||||||
|
with patch.object(_ctx_module._sys, "platform", "darwin"):
|
||||||
|
with patch.object(SSLContext, "_load_certifi") as mock_certifi:
|
||||||
|
with patch("OpenSSL.SSL.Context.set_default_verify_paths"):
|
||||||
|
ctx = SSLContext(PROTOCOL_SSLv23)
|
||||||
|
ctx.load_default_certs()
|
||||||
|
mock_certifi.assert_called()
|
||||||
|
|
||||||
|
@unittest.skipUnless(_HAVE_PYOPENSSL, "PyOpenSSL is not available.")
|
||||||
|
def test_win32_calls_load_wincerts(self):
|
||||||
|
with patch.object(_ctx_module._sys, "platform", "win32"):
|
||||||
|
with patch.object(SSLContext, "_load_wincerts") as mock_wincerts:
|
||||||
|
with patch("OpenSSL.SSL.Context.set_default_verify_paths"):
|
||||||
|
ctx = SSLContext(PROTOCOL_SSLv23)
|
||||||
|
ctx.load_default_certs()
|
||||||
|
calls = [call.args[0] for call in mock_wincerts.call_args_list]
|
||||||
|
self.assertIn("CA", calls)
|
||||||
|
self.assertIn("ROOT", calls)
|
||||||
|
|
||||||
|
@unittest.skipUnless(_HAVE_PYOPENSSL, "PyOpenSSL is not available.")
|
||||||
|
def test_win32_falls_back_to_certifi_on_exception(self):
|
||||||
|
with patch.object(_ctx_module._sys, "platform", "win32"):
|
||||||
|
with patch.object(SSLContext, "_load_wincerts", side_effect=Exception("no certs")):
|
||||||
|
with patch.object(SSLContext, "_load_certifi") as mock_certifi:
|
||||||
|
with patch("OpenSSL.SSL.Context.set_default_verify_paths"):
|
||||||
|
ctx = SSLContext(PROTOCOL_SSLv23)
|
||||||
|
ctx.load_default_certs()
|
||||||
|
mock_certifi.assert_called()
|
||||||
|
|
||||||
|
@unittest.skipUnless(_HAVE_PYOPENSSL, "PyOpenSSL is not available.")
|
||||||
|
def test_linux_no_certifi_call(self):
|
||||||
|
with patch.object(_ctx_module._sys, "platform", "linux"):
|
||||||
|
with patch.object(SSLContext, "_load_certifi") as mock_certifi:
|
||||||
|
with patch("OpenSSL.SSL.Context.set_default_verify_paths"):
|
||||||
|
ctx = SSLContext(PROTOCOL_SSLv23)
|
||||||
|
ctx.load_default_certs()
|
||||||
|
mock_certifi.assert_not_called()
|
||||||
|
|
||||||
|
@unittest.skipUnless(_HAVE_PYOPENSSL, "PyOpenSSL is not available.")
|
||||||
|
def test_calls_set_default_verify_paths(self):
|
||||||
|
with patch.object(_ctx_module._sys, "platform", "linux"):
|
||||||
|
ctx = SSLContext(PROTOCOL_SSLv23)
|
||||||
|
with patch.object(ctx._ctx, "set_default_verify_paths") as mock_sdvp:
|
||||||
|
ctx.load_default_certs()
|
||||||
|
mock_sdvp.assert_called_once()
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# SSLContext.set_default_verify_paths
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
class TestSetDefaultVerifyPaths(unittest.TestCase):
|
||||||
|
@unittest.skipUnless(_HAVE_PYOPENSSL, "PyOpenSSL is not available.")
|
||||||
|
def test_delegates_to_ctx(self):
|
||||||
|
ctx = SSLContext(PROTOCOL_SSLv23)
|
||||||
|
with patch.object(ctx._ctx, "set_default_verify_paths") as mock_sdvp:
|
||||||
|
ctx.set_default_verify_paths()
|
||||||
|
mock_sdvp.assert_called_once()
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# SSLContext.load_verify_locations
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
class TestLoadVerifyLocations(unittest.TestCase):
|
||||||
|
@unittest.skipUnless(_HAVE_PYOPENSSL, "PyOpenSSL is not available.")
|
||||||
|
def test_delegates_to_ctx(self):
|
||||||
|
ctx = SSLContext(PROTOCOL_SSLv23)
|
||||||
|
with patch.object(ctx._ctx, "load_verify_locations") as mock_lvl:
|
||||||
|
ctx.load_verify_locations(cafile="/tmp/ca.pem")
|
||||||
|
mock_lvl.assert_called_once_with("/tmp/ca.pem", None)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
Loading…
Reference in New Issue
Block a user